librw/src/gl/gl3raster.cpp

331 lines
7.1 KiB
C++
Raw Normal View History

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#ifdef RW_OPENGL
#include <GL/glew.h>
#endif
#include "rwgl3.h"
#include "rwgl3shader.h"
#define PLUGIN_ID ID_DRIVER
namespace rw {
namespace gl3 {
int32 nativeRasterOffset;
#ifdef RW_OPENGL
static Raster*
2020-04-16 17:46:42 +02:00
rasterCreateTexture(Raster *raster)
{
2020-04-16 17:46:42 +02:00
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
switch(raster->format & 0xF00){
case Raster::C8888:
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 1;
break;
2020-04-16 17:46:42 +02:00
case Raster::C888:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 0;
break;
2020-04-16 17:46:42 +02:00
case Raster::C1555:
// TODO: check if this is correct
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_5_5_5_1;
natras->hasAlpha = 1;
break;
default:
RWERROR((ERR_INVRASTER));
return nil;
}
2020-04-16 17:46:42 +02:00
glGenTextures(1, &natras->texid);
glBindTexture(GL_TEXTURE_2D, natras->texid);
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, nil);
natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
glBindTexture(GL_TEXTURE_2D, 0);
return raster;
2020-04-16 17:46:42 +02:00
}
2020-04-16 17:46:42 +02:00
// This is totally fake right now, can't render to it. Only used to copy into from FB
// For rendering the idea would probably be to render to the backbuffer and copy it here afterwards.
// alternatively just use FBOs but that probably needs some more infrastructure.
static Raster*
2020-04-16 17:46:42 +02:00
rasterCreateCameraTexture(Raster *raster)
{
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
RWERROR((ERR_NOTEXTURE));
return nil;
}
2020-04-16 17:46:42 +02:00
// TODO: figure out what the backbuffer is and use that as a default
2016-07-15 11:55:52 +02:00
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
switch(raster->format & 0xF00){
case Raster::C8888:
2020-04-16 17:46:42 +02:00
default:
2016-07-15 11:55:52 +02:00
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_BYTE;
2016-07-15 11:55:52 +02:00
natras->hasAlpha = 1;
break;
case Raster::C888:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_BYTE;
2016-07-15 11:55:52 +02:00
natras->hasAlpha = 0;
break;
case Raster::C1555:
// TODO: check if this is correct
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_5_5_5_1;
natras->hasAlpha = 1;
break;
2016-07-15 11:55:52 +02:00
}
glGenTextures(1, &natras->texid);
glBindTexture(GL_TEXTURE_2D, natras->texid);
2016-07-15 11:55:52 +02:00
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, nil);
natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
glBindTexture(GL_TEXTURE_2D, 0);
return raster;
2020-04-16 17:46:42 +02:00
}
static Raster*
2020-04-16 17:46:42 +02:00
rasterCreateCamera(Raster *raster)
{
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->stride = 0;
raster->pixels = nil;
return raster;
2020-04-16 17:46:42 +02:00
}
static Raster*
2020-04-16 17:46:42 +02:00
rasterCreateZbuffer(Raster *raster)
{
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
return raster;
2020-04-16 17:46:42 +02:00
}
#endif
Raster*
2020-04-16 17:46:42 +02:00
rasterCreate(Raster *raster)
{
switch(raster->type){
#ifdef RW_OPENGL
2020-04-16 17:46:42 +02:00
case Raster::NORMAL:
case Raster::TEXTURE:
// Dummy to use as subraster
// ^ what did i do there?
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
return raster;
2020-04-16 17:46:42 +02:00
}
if(raster->flags & Raster::DONTALLOCATE)
return raster;
return rasterCreateTexture(raster);
2020-04-16 17:46:42 +02:00
case Raster::CAMERATEXTURE:
if(raster->flags & Raster::DONTALLOCATE)
return raster;
return rasterCreateCameraTexture(raster);
2020-04-16 17:46:42 +02:00
case Raster::ZBUFFER:
return rasterCreateZbuffer(raster);
2020-04-16 17:46:42 +02:00
case Raster::CAMERA:
return rasterCreateCamera(raster);
#endif
2020-04-16 17:46:42 +02:00
default:
RWERROR((ERR_INVRASTER));
return nil;
2020-04-16 17:46:42 +02:00
}
}
uint8*
2019-08-07 22:37:43 +02:00
rasterLock(Raster*, int32 level, int32 lockMode)
{
printf("locking\n");
return nil;
}
void
rasterUnlock(Raster*, int32)
{
printf("unlocking\n");
}
int32
rasterNumLevels(Raster*)
{
printf("numlevels\n");
return 0;
}
// Almost the same as d3d9 and ps2 function
bool32
imageFindRasterFormat(Image *img, int32 type,
int32 *pWidth, int32 *pHeight, int32 *pDepth, int32 *pFormat)
{
int32 width, height, depth, format;
assert((type&0xF) == Raster::TEXTURE);
for(width = 1; width < img->width; width <<= 1);
for(height = 1; height < img->height; height <<= 1);
depth = img->depth;
if(depth <= 8)
depth = 32;
switch(depth){
case 32:
if(img->hasAlpha())
format = Raster::C8888;
else{
format = Raster::C888;
depth = 24;
}
break;
case 24:
format = Raster::C888;
break;
case 16:
format = Raster::C1555;
break;
case 8:
case 4:
default:
RWERROR((ERR_INVRASTER));
return 0;
}
format |= type;
*pWidth = width;
*pHeight = height;
*pDepth = depth;
*pFormat = format;
return 1;
}
bool32
rasterFromImage(Raster *raster, Image *image)
{
if((raster->type&0xF) != Raster::TEXTURE)
return 0;
// Unpalettize image if necessary but don't change original
Image *truecolimg = nil;
if(image->depth <= 8){
truecolimg = Image::create(image->width, image->height, image->depth);
truecolimg->pixels = image->pixels;
truecolimg->stride = image->stride;
truecolimg->palette = image->palette;
truecolimg->unindex();
image = truecolimg;
}
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
2016-07-15 11:55:52 +02:00
switch(image->depth){
case 32:
if(raster->format != Raster::C8888 &&
raster->format != Raster::C888)
goto err;
2016-07-15 11:55:52 +02:00
break;
case 24:
if(raster->format != Raster::C888) goto err;
2016-07-15 11:55:52 +02:00
break;
case 16:
if(raster->format != Raster::C1555) goto err;
break;
case 8:
case 4:
2016-07-15 11:55:52 +02:00
default:
err:
RWERROR((ERR_INVRASTER));
return 0;
2016-07-15 11:55:52 +02:00
}
natras->hasAlpha = image->hasAlpha();
#ifdef RW_OPENGL
glBindTexture(GL_TEXTURE_2D, natras->texid);
2016-07-15 11:55:52 +02:00
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, image->pixels);
glBindTexture(GL_TEXTURE_2D, 0);
#endif
return 1;
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
ras->texid = 0;
return object;
}
static void*
destroyNativeRaster(void *object, int32, int32)
{
//Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
// TODO
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
Gl3Raster *d = PLUGINOFFSET(Gl3Raster, dst, offset);
d->texid = 0;
return dst;
}
void registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(Gl3Raster),
ID_RASTERGL3,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
}
}
}