Make gles1 stubs based on gl3 code

This commit is contained in:
Shinovon 2026-05-01 12:36:04 +05:00
parent 2c441fbede
commit 6d11126db6
13 changed files with 3595 additions and 155 deletions

View file

@ -14,7 +14,7 @@ SOURCE engine.cpp error.cpp frame.cpp geometry.cpp geoplg.cpp
SOURCEPATH ../vendor/librw/src/gl SOURCEPATH ../vendor/librw/src/gl
SOURCE gl3.cpp gl3device.cpp gl3immed.cpp gl3matfx.cpp gl3pipe.cpp gl3raster.cpp gl3render.cpp gl3shader.cpp gl3skin.cpp wdgl.cpp SOURCE gl3.cpp gl3device.cpp gl3immed.cpp gl3matfx.cpp gl3pipe.cpp gl3raster.cpp gl3render.cpp gl3shader.cpp gl3skin.cpp wdgl.cpp
SOURCEPATH ../vendor/librw/src/gles1 SOURCEPATH ../vendor/librw/src/gles1
SOURCE rwgles1.cpp SOURCE gl1.cpp gl1device.cpp gl1immed.cpp gl1pipe.cpp gl1raster.cpp gl1render.cpp
SOURCEPATH ../vendor/librw/src SOURCEPATH ../vendor/librw/src
SOURCE hanim.cpp image.cpp light.cpp SOURCE hanim.cpp image.cpp light.cpp
SOURCEPATH ../vendor/librw/src/lodepng SOURCEPATH ../vendor/librw/src/lodepng

View file

@ -244,6 +244,9 @@ Engine::init(MemoryFunctions *memfuncs)
d3d9::registerPlatformPlugins(); d3d9::registerPlatformPlugins();
wdgl::registerPlatformPlugins(); wdgl::registerPlatformPlugins();
gl3::registerPlatformPlugins(); gl3::registerPlatformPlugins();
#ifdef RW_GLES1
gles1::registerPlatformPlugins();
#endif
Engine::state = Initialized; Engine::state = Initialized;
return 1; return 1;
@ -269,8 +272,8 @@ Engine::open(EngineOpenParams *p)
engine->device = ps2::renderdevice; engine->device = ps2::renderdevice;
#elif RW_GL3 #elif RW_GL3
engine->device = gl3::renderdevice; engine->device = gl3::renderdevice;
//#elif RW_GLES1 // TODO #elif RW_GLES1
// engine->device = gles1::renderdevice; engine->device = gles1::renderdevice;
#elif RW_D3D9 #elif RW_D3D9
engine->device = d3d::renderdevice; engine->device = d3d::renderdevice;
#else #else

54
vendor/librw/src/gles1/gl1.cpp vendored Normal file
View file

@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwgles1.h"
#include "rwgles1impl.h"
#ifdef RW_GLES1
namespace rw {
namespace gles1 {
static void*
driverOpen(void* object, int32 offset, int32 size)
{
engine->driver[PLATFORM_GLES1]->defaultPipeline = makeDefaultPipeline();
engine->driver[PLATFORM_GLES1]->rasterNativeOffset = nativeRasterOffset;
engine->driver[PLATFORM_GLES1]->rasterCreate = rasterCreate;
engine->driver[PLATFORM_GLES1]->rasterLock = rasterLock;
engine->driver[PLATFORM_GLES1]->rasterUnlock = rasterUnlock;
engine->driver[PLATFORM_GLES1]->rasterNumLevels = rasterNumLevels;
engine->driver[PLATFORM_GLES1]->imageFindRasterFormat = imageFindRasterFormat;
engine->driver[PLATFORM_GLES1]->rasterFromImage = rasterFromImage;
engine->driver[PLATFORM_GLES1]->rasterToImage = rasterToImage;
return object;
}
static void*
driverClose(void* object, int32 offset, int32 size)
{
// stub: no hace nada
return object;
}
void
registerPlatformPlugins(void)
{
Driver::registerPlugin(PLATFORM_GLES1, 0, PLATFORM_GLES1,
driverOpen, driverClose);
registerNativeRaster();
}
}
}
#endif

1610
vendor/librw/src/gles1/gl1device.cpp vendored Normal file

File diff suppressed because it is too large Load diff

180
vendor/librw/src/gles1/gl1immed.cpp vendored Normal file
View file

@ -0,0 +1,180 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#ifdef RW_GLES1
#include "rwgles1.h"
#include "rwgles1impl.h"
namespace rw {
namespace gles1 {
uint32 im2DVbo, im2DIbo;
static AttribDesc im2dattribDesc[3] = {
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 4,
sizeof(Im2DVertex), 0 },
{ ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im2DVertex), offsetof(Im2DVertex, r) },
{ ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im2DVertex), offsetof(Im2DVertex, u) },
};
static int primTypeMap[] = {
GL_POINTS, // invalid
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_TRIANGLE_FAN,
GL_POINTS
};
void
openIm2D(void)
{
}
void
closeIm2D(void)
{
}
static Im2DVertex tmpprimbuf[3];
void
im2DRenderLine(void *vertices, int32 numVertices, int32 vert1, int32 vert2)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
im2DRenderPrimitive(PRIMTYPELINELIST, tmpprimbuf, 2);
}
void
im2DRenderTriangle(void *vertices, int32 numVertices, int32 vert1, int32 vert2, int32 vert3)
{
Im2DVertex *verts = (Im2DVertex*)vertices;
tmpprimbuf[0] = verts[vert1];
tmpprimbuf[1] = verts[vert2];
tmpprimbuf[2] = verts[vert3];
im2DRenderPrimitive(PRIMTYPETRILIST, tmpprimbuf, 3);
}
void
im2DRenderPrimitive(PrimitiveType primType, void *vertices, int32 numVertices)
{
Camera *cam;
cam = (Camera*)engine->currentCamera;
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_STATIC_DRAW);
flushCache();
glDrawArrays(primTypeMap[primType], 0, numVertices);
}
void
im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices,
void *indices, int32 numIndices)
{
Camera *cam;
cam = (Camera*)engine->currentCamera;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im2DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, im2DVbo);
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im2DVertex), vertices, GL_STATIC_DRAW);
flushCache();
glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil);
}
// Im3D
static AttribDesc im3dattribDesc[3] = {
{ ATTRIB_POS, GL_FLOAT, GL_FALSE, 3,
sizeof(Im3DVertex), 0 },
{ ATTRIB_COLOR, GL_UNSIGNED_BYTE, GL_TRUE, 4,
sizeof(Im3DVertex), offsetof(Im3DVertex, r) },
{ ATTRIB_TEXCOORDS0, GL_FLOAT, GL_FALSE, 2,
sizeof(Im3DVertex), offsetof(Im3DVertex, u) },
};
static uint32 im3DVbo, im3DIbo;
static int32 num3DVertices; // not actually needed here
static void* currentIm3dVertices;
void
openIm3D(void)
{
glGenBuffers(1, &im3DIbo);
glGenBuffers(1, &im3DVbo);
}
void
closeIm3D(void)
{
glDeleteBuffers(1, &im3DIbo);
glDeleteBuffers(1, &im3DVbo);
}
void
im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags)
{
if(world == nil){
static Matrix ident;
ident.setIdentity();
world = &ident;
}
setWorldMatrix(world);
if((flags & im3d::VERTEXUV) == 0)
SetRenderStatePtr(TEXTURERASTER, nil);
glBindBuffer(GL_ARRAY_BUFFER, im3DVbo);
glBufferData(GL_ARRAY_BUFFER, numVertices*sizeof(Im3DVertex), vertices, GL_DYNAMIC_DRAW);
num3DVertices = numVertices;
}
void
im3DRenderPrimitive(PrimitiveType primType)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo);
flushCache();
glDrawArrays(primTypeMap[primType], 0, num3DVertices);
}
void
im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, im3DIbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, indices, GL_STATIC_DRAW);
flushCache();
glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil);
}
void
im3DEnd(void)
{
}
}
}
#endif

317
vendor/librw/src/gles1/gl1pipe.cpp vendored Normal file
View file

@ -0,0 +1,317 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwgles1.h"
namespace rw {
namespace gles1 {
// TODO: make some of these things platform-independent
#ifdef RW_GLES1
void
freeInstanceData(Geometry *geometry)
{
if(geometry->instData == nil ||
geometry->instData->platform != PLATFORM_GLES1)
return;
InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData;
geometry->instData = nil;
glDeleteBuffers(1, &header->ibo);
glDeleteBuffers(1, &header->vbo);
rwFree(header->indexBuffer);
rwFree(header->vertexBuffer);
rwFree(header->attribDesc);
rwFree(header->inst);
rwFree(header);
}
void*
destroyNativeData(void *object, int32, int32)
{
freeInstanceData((Geometry*)object);
return object;
}
static InstanceDataHeader*
instanceMesh(rw::ObjPipeline *rwpipe, Geometry *geo)
{
InstanceDataHeader *header = rwNewT(InstanceDataHeader, 1, MEMDUR_EVENT | ID_GEOMETRY);
MeshHeader *meshh = geo->meshHeader;
geo->instData = header;
header->platform = PLATFORM_GLES1;
header->serialNumber = meshh->serialNum;
header->numMeshes = meshh->numMeshes;
header->primType = meshh->flags == 1 ? GL_TRIANGLE_STRIP : GL_TRIANGLES;
header->totalNumVertex = geo->numVertices;
header->totalNumIndex = meshh->totalIndices;
header->inst = rwNewT(InstanceData, header->numMeshes, MEMDUR_EVENT | ID_GEOMETRY);
header->indexBuffer = rwNewT(uint16, header->totalNumIndex, MEMDUR_EVENT | ID_GEOMETRY);
InstanceData *inst = header->inst;
Mesh *mesh = meshh->getMeshes();
uint32 offset = 0;
for(uint32 i = 0; i < header->numMeshes; i++){
findMinVertAndNumVertices(mesh->indices, mesh->numIndices,
&inst->minVert, &inst->numVertices);
assert(inst->minVert != 0xFFFFFFFF);
inst->numIndex = mesh->numIndices;
inst->material = mesh->material;
inst->vertexAlpha = 0;
inst->program = 0;
inst->offset = offset;
memcpy((uint8*)header->indexBuffer + inst->offset,
mesh->indices, inst->numIndex*2);
offset += inst->numIndex*2;
mesh++;
inst++;
}
header->vertexBuffer = nil;
header->numAttribs = 0;
header->attribDesc = nil;
header->ibo = 0;
header->vbo = 0;
glGenBuffers(1, &header->ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, header->totalNumIndex*2,
header->indexBuffer, GL_STATIC_DRAW);
return header;
}
static void
instance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
// don't try to (re)instance native data
if(geo->flags & Geometry::NATIVE)
return;
InstanceDataHeader *header = (InstanceDataHeader*)geo->instData;
if(geo->instData){
// Already have instanced data, so check if we have to reinstance
assert(header->platform == PLATFORM_GLES1);
if(header->serialNumber != geo->meshHeader->serialNum){
// Mesh changed, so reinstance everything
freeInstanceData(geo);
}
}
// no instance or complete reinstance
if(geo->instData == nil){
geo->instData = instanceMesh(rwpipe, geo);
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 0);
}else if(geo->lockedSinceInst)
pipe->instanceCB(geo, (InstanceDataHeader*)geo->instData, 1);
geo->lockedSinceInst = 0;
}
static void
uninstance(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
assert(0 && "can't uninstance");
}
static void
render(rw::ObjPipeline *rwpipe, Atomic *atomic)
{
ObjPipeline *pipe = (ObjPipeline*)rwpipe;
Geometry *geo = atomic->geometry;
pipe->instance(atomic);
assert(geo->instData != nil);
assert(geo->instData->platform == PLATFORM_GLES1);
if(pipe->renderCB)
pipe->renderCB(atomic, (InstanceDataHeader*)geo->instData);
}
void
ObjPipeline::init(void)
{
this->rw::ObjPipeline::init(PLATFORM_GLES1);
this->impl.instance = gles1::instance;
this->impl.uninstance = gles1::uninstance;
this->impl.render = gles1::render;
this->instanceCB = nil;
this->uninstanceCB = nil;
this->renderCB = nil;
}
ObjPipeline*
ObjPipeline::create(void)
{
ObjPipeline *pipe = rwNewT(ObjPipeline, 1, MEMDUR_GLOBAL);
pipe->init();
return pipe;
}
void
defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance)
{
AttribDesc *attribs, *a;
bool isPrelit = !!(geo->flags & Geometry::PRELIT);
bool hasNormals = !!(geo->flags & Geometry::NORMALS);
if(!reinstance){
AttribDesc tmpAttribs[12];
uint32 stride;
//
// Create attribute descriptions
//
a = tmpAttribs;
stride = 0;
// Positions
a->index = ATTRIB_POS;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
// Normals
// TODO: compress
if(hasNormals){
a->index = ATTRIB_NORMAL;
a->size = 3;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 12;
a++;
}
// Prelighting
if(isPrelit){
a->index = ATTRIB_COLOR;
a->size = 4;
a->type = GL_UNSIGNED_BYTE;
a->normalized = GL_TRUE;
a->offset = stride;
stride += 4;
a++;
}
// Texture coordinates
for(int32 n = 0; n < geo->numTexCoordSets; n++){
a->index = ATTRIB_TEXCOORDS0+n;
a->size = 2;
a->type = GL_FLOAT;
a->normalized = GL_FALSE;
a->offset = stride;
stride += 8;
a++;
}
header->numAttribs = a - tmpAttribs;
for(a = tmpAttribs; a != &tmpAttribs[header->numAttribs]; a++)
a->stride = stride;
header->attribDesc = rwNewT(AttribDesc, header->numAttribs, MEMDUR_EVENT | ID_GEOMETRY);
memcpy(header->attribDesc, tmpAttribs,
header->numAttribs*sizeof(AttribDesc));
//
// Allocate vertex buffer
//
header->vertexBuffer = rwNewT(uint8, header->totalNumVertex*stride, MEMDUR_EVENT | ID_GEOMETRY);
assert(header->vbo == 0);
glGenBuffers(1, &header->vbo);
}
attribs = header->attribDesc;
//
// Fill vertex buffer
//
uint8 *verts = header->vertexBuffer;
// Positions
if(!reinstance || geo->lockedSinceInst&Geometry::LOCKVERTICES){
for(a = attribs; a->index != ATTRIB_POS; a++)
;
instV3d(VERT_FLOAT3, verts + a->offset,
geo->morphTargets[0].vertices,
header->totalNumVertex, a->stride);
}
// Normals
if(hasNormals && (!reinstance || geo->lockedSinceInst&Geometry::LOCKNORMALS)){
for(a = attribs; a->index != ATTRIB_NORMAL; a++)
;
instV3d(VERT_FLOAT3, verts + a->offset,
geo->morphTargets[0].normals,
header->totalNumVertex, a->stride);
}
// Prelighting
if(isPrelit && (!reinstance || geo->lockedSinceInst&Geometry::LOCKPRELIGHT)){
for(a = attribs; a->index != ATTRIB_COLOR; a++)
;
int n = header->numMeshes;
InstanceData *inst = header->inst;
while(n--){
assert(inst->minVert != 0xFFFFFFFF);
inst->vertexAlpha = instColor(VERT_RGBA,
verts + a->offset + a->stride*inst->minVert,
geo->colors + inst->minVert,
inst->numVertices, a->stride);
inst++;
}
}
// Texture coordinates
for(int32 n = 0; n < geo->numTexCoordSets; n++){
if(!reinstance || geo->lockedSinceInst&(Geometry::LOCKTEXCOORDS<<n)){
for(a = attribs; a->index != ATTRIB_TEXCOORDS0+n; a++)
;
instTexCoords(VERT_FLOAT2, verts + a->offset,
geo->texCoords[n],
header->totalNumVertex, a->stride);
}
}
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
glBufferData(GL_ARRAY_BUFFER, header->totalNumVertex*attribs[0].stride,
header->vertexBuffer, GL_STATIC_DRAW);
}
void
defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header)
{
assert(0 && "can't uninstance");
}
ObjPipeline*
makeDefaultPipeline(void)
{
ObjPipeline *pipe = ObjPipeline::create();
pipe->instanceCB = defaultInstanceCB;
pipe->uninstanceCB = defaultUninstanceCB;
pipe->renderCB = defaultRenderCB;
return pipe;
}
#else
void *destroyNativeData(void *object, int32, int32) { return object; }
#endif
}
}

961
vendor/librw/src/gles1/gl1raster.cpp vendored Normal file
View file

@ -0,0 +1,961 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#include "rwgles1.h"
#include "rwgles1impl.h"
#define PLUGIN_ID ID_DRIVER
namespace rw {
namespace gles1 {
int32 nativeRasterOffset;
static uint32
getLevelSize(Raster *raster, int32 level)
{
int i;
Gl1Raster *natras = GETGL1RASTEREXT(raster);
int w = raster->originalWidth;
int h = raster->originalHeight;
int s = raster->originalStride;
int minDim = 1;
//#ifdef RW_GLES1
// switch(natras->internalFormat){
// case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
// case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
// case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
// case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
// minDim = 4;
// break;
// }
//#endif
for(i = 0; i < level; i++){
if(w > minDim){
w /= 2;
s /= 2;
}
if(h > minDim)
h /= 2;
}
return s*h;
}
#ifdef RW_GLES1
static Raster*
rasterCreateTexture(Raster *raster)
{
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
RWERROR((ERR_NOTEXTURE));
return nil;
}
Gl1Raster *natras = GETGL1RASTEREXT(raster);
switch(raster->format & 0xF00){
case Raster::C8888:
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 1;
natras->bpp = 4;
raster->depth = 32;
break;
case Raster::C888:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 0;
natras->bpp = 3;
raster->depth = 24;
break;
case Raster::C565:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_SHORT_5_6_5;
natras->hasAlpha = 0;
natras->bpp = 2;
raster->depth = 16;
break;
case Raster::C4444:
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_4_4_4_4;
natras->hasAlpha = 1;
natras->bpp = 2;
raster->depth = 16;
break;
case Raster::C1555:
// natras->internalFormat = GL_RGB5_A1;
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_5_5_5_1;
natras->hasAlpha = 1;
natras->bpp = 2;
raster->depth = 16;
break;
default:
RWERROR((ERR_INVRASTER));
return nil;
}
natras->internalFormat = natras->format;
raster->stride = raster->width*natras->bpp;
if(raster->format & Raster::MIPMAP){
int w = raster->width;
int h = raster->height;
natras->numLevels = 1;
while(w != 1 || h != 1){
natras->numLevels++;
if(w > 1) w /= 2;
if(h > 1) h /= 2;
}
}
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
if(natras->autogenMipmap)
natras->numLevels = 1;
glGenTextures(1, &natras->texid);
uint32 prev = bindTexture(natras->texid);
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
// raster->width, raster->height,
1,1,
0, natras->format, natras->type, nil);
// TODO: allocate other levels...probably
natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
natras->maxAnisotropy = 1;
bindTexture(prev);
return raster;
}
static Raster*
rasterCreateCameraTexture(Raster *raster)
{
if(raster->format & (Raster::PAL4 | Raster::PAL8)){
RWERROR((ERR_NOTEXTURE));
return nil;
}
// TODO: figure out what the backbuffer is and use that as a default
Gl1Raster *natras = GETGL1RASTEREXT(raster);
switch(raster->format & 0xF00){
case Raster::C8888:
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 1;
natras->bpp = 4;
break;
case Raster::C4444:
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_4_4_4_4;
natras->hasAlpha = 1;
natras->bpp = 2;
break;
case Raster::C888:
default:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_BYTE;
natras->hasAlpha = 0;
natras->bpp = 3;
break;
case Raster::C565:
natras->internalFormat = GL_RGB;
natras->format = GL_RGB;
natras->type = GL_UNSIGNED_SHORT_5_6_5;
natras->hasAlpha = 0;
natras->bpp = 2;
break;
case Raster::C1555:
// natras->internalFormat = GL_RGB5_A1;
natras->internalFormat = GL_RGBA;
natras->format = GL_RGBA;
natras->type = GL_UNSIGNED_SHORT_5_5_5_1;
natras->hasAlpha = 1;
natras->bpp = 2;
break;
}
natras->internalFormat = natras->format;
raster->stride = raster->width*natras->bpp;
natras->autogenMipmap = (raster->format & (Raster::MIPMAP|Raster::AUTOMIPMAP)) == (Raster::MIPMAP|Raster::AUTOMIPMAP);
glGenTextures(1, &natras->texid);
uint32 prev = bindTexture(natras->texid);
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
// raster->width, raster->height,
1,1,
0, natras->format, natras->type, nil);
natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
natras->maxAnisotropy = 1;
bindTexture(prev);
// glGenFramebuffers(1, &natras->fbo);
// bindFramebuffer(natras->fbo);
// glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0);
// bindFramebuffer(0);
natras->fboMate = nil;
return raster;
}
static Raster*
rasterCreateCamera(Raster *raster)
{
Gl1Raster *natras = GETGL1RASTEREXT(raster);
// TODO: set/check width, height, depth, format?
// used for locking right now
// raster->format = Raster::C888;
// natras->internalFormat = GL_RGB;
// natras->format = GL_RGB;
// natras->type = GL_UNSIGNED_BYTE;
// natras->hasAlpha = 0;
// natras->bpp = 3;
//
// natras->autogenMipmap = 0;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->stride = 0;
raster->pixels = nil;
natras->texid = 0;
natras->fbo = 0;
natras->fboMate = nil;
return raster;
}
static Raster*
rasterCreateZbuffer(Raster *raster)
{
Gl1Raster *natras = GETGL1RASTEREXT(raster);
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->stride = 0;
raster->pixels = nil;
// if(gl1Caps.gles){
// // have to use RBO on GLES!!
// glGenRenderbuffers(1, &natras->texid);
// glBindRenderbuffer(GL_RENDERBUFFER, natras->texid);
//#ifdef __SYMBIAN32__
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, raster->width, raster->height);
//#else
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, raster->width, raster->height);
//#endif
//#ifndef __SYMBIAN32__
// }else{
// // TODO: set/check width, height, depth, format?
// natras->internalFormat = GL_DEPTH_STENCIL;
// natras->format = GL_DEPTH_STENCIL;
// natras->type = GL_UNSIGNED_INT_24_8;
//
// natras->autogenMipmap = 0;
//
// glGenTextures(1, &natras->texid);
// uint32 prev = bindTexture(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;
// natras->maxAnisotropy = 1;
//
// bindTexture(prev);
//#endif
// }
// natras->fbo = 0;
// natras->fboMate = nil;
return raster;
}
#endif
/*
{ 0, 0, 0 },
{ 16, 4, GL_RGBA }, // 1555
{ 16, 3, GL_RGB }, // 565
{ 16, 4, GL_RGBA }, // 4444
{ 0, 0, 0 }, // LUM8
{ 32, 4, GL_RGBA }, // 8888
{ 24, 3, GL_RGB }, // 888
{ 16, 3, GL_RGB }, // D16
{ 24, 3, GL_RGB }, // D24
{ 32, 4, GL_RGBA }, // D32
{ 16, 3, GL_RGB }, // 555
0,
GL_RGB5_A1,
GL_RGB5,
GL_RGBA4,
0,
GL_RGBA8,
GL_RGB8,
GL_RGB5,
GL_RGB8,
GL_RGBA8,
GL_RGB5
*/
Raster*
rasterCreate(Raster *raster)
{
Gl1Raster *natras = GETGL1RASTEREXT(raster);
natras->isCompressed = 0;
natras->hasAlpha = 0;
natras->numLevels = 1;
Raster *ret = raster;
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
goto ret;
}
if(raster->flags & Raster::DONTALLOCATE)
goto ret;
switch(raster->type){
#ifdef RW_GLES1
case Raster::NORMAL:
case Raster::TEXTURE:
ret = rasterCreateTexture(raster);
break;
case Raster::CAMERATEXTURE:
ret = rasterCreateCameraTexture(raster);
break;
case Raster::ZBUFFER:
ret = rasterCreateZbuffer(raster);
break;
case Raster::CAMERA:
ret = rasterCreateCamera(raster);
break;
#endif
default:
RWERROR((ERR_INVRASTER));
return nil;
}
ret:
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->originalStride = raster->stride;
raster->originalPixels = raster->pixels;
return ret;
}
uint8*
rasterLock(Raster *raster, int32 level, int32 lockMode)
{
#ifdef RW_GLES1
Gl1Raster *natras GETGL1RASTEREXT(raster);
uint8 *px;
uint32 allocSz;
int i;
assert(raster->privateFlags == 0);
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
case Raster::CAMERATEXTURE:
for(i = 0; i < level; i++){
if(raster->width > 1){
raster->width /= 2;
raster->stride /= 2;
}
if(raster->height > 1)
raster->height /= 2;
}
allocSz = getLevelSize(raster, level);
px = (uint8*)rwMalloc(allocSz, MEMDUR_EVENT | ID_DRIVER);
assert(raster->pixels == nil);
raster->pixels = px;
if(lockMode & Raster::LOCKREAD || !(lockMode & Raster::LOCKNOFETCH)){
if(natras->isCompressed){
if(natras->backingStore){
assert(level < natras->backingStore->numlevels);
assert(allocSz >= natras->backingStore->levels[level].size);
memcpy(px, natras->backingStore->levels[level].data, allocSz);
}else{
// GLES is losing here
}
} else {
// TODO
}
}
raster->privateFlags = lockMode;
break;
case Raster::CAMERA:
if(lockMode & Raster::PRIVATELOCK_WRITE)
assert(0 && "can't lock framebuffer for writing");
raster->width = glGlobals.presentWidth;
raster->height = glGlobals.presentHeight;
raster->stride = raster->width*natras->bpp;
assert(natras->bpp == 3);
allocSz = raster->height*raster->stride;
px = (uint8*)rwMalloc(allocSz, MEMDUR_EVENT | ID_DRIVER);
assert(raster->pixels == nil);
raster->pixels = px;
#ifdef __SYMBIAN32__
memset(px, 0, allocSz);
#else
glReadBuffer(GL_BACK);
#endif
glReadPixels(0, 0, raster->width, raster->height, GL_RGB, GL_UNSIGNED_BYTE, px);
raster->privateFlags = lockMode;
break;
default:
assert(0 && "cannot lock this type of raster yet");
return nil;
}
return px;
#else
return nil;
#endif
}
void
rasterUnlock(Raster *raster, int32 level)
{
#ifdef RW_GLES1
Gl1Raster *natras = GETGL1RASTEREXT(raster);
assert(raster->pixels);
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
case Raster::CAMERATEXTURE:
if(raster->privateFlags & Raster::LOCKWRITE){
if (level != 0) break;
uint32 prev = bindTexture(natras->texid);
if(natras->isCompressed){
glCompressedTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
raster->width, raster->height, 0,
getLevelSize(raster, level),
raster->pixels);
if(natras->backingStore){
assert(level < natras->backingStore->numlevels);
memcpy(natras->backingStore->levels[level].data, raster->pixels,
natras->backingStore->levels[level].size);
}
}else{
if (raster->pixels != nil && natras->format == GL_RGBA && natras->type == GL_UNSIGNED_BYTE) {
// convert to 16-bit
uint16_t* pixels16 = (uint16_t*)malloc(raster->width * raster->height * sizeof(uint16_t));
uint8_t* pixels8 = (uint8_t*)raster->pixels;
for (int i = 0; i < raster->width * raster->height; i++) {
uint8_t r = pixels8[i * 4 + 0];
uint8_t g = pixels8[i * 4 + 1];
uint8_t b = pixels8[i * 4 + 2];
uint8_t a = pixels8[i * 4 + 3];
pixels16[i] = ((r >> 4) << 12) | ((g >> 4) << 8) | ((b >> 4) << 4) | (a >> 4);
}
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, raster->width, raster->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels16);
free(pixels16);
} else
{
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, level, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, raster->pixels);
}
}
// if(level == 0 && natras->autogenMipmap)
// glGenerateMipmap(GL_TEXTURE_2D);
bindTexture(prev);
}
break;
case Raster::CAMERA:
// TODO: write?
break;
}
rwFree(raster->pixels);
raster->pixels = nil;
#endif
raster->width = raster->originalWidth;
raster->height = raster->originalHeight;
raster->stride = raster->originalStride;
raster->pixels = raster->originalPixels;
raster->privateFlags = 0;
}
int32
rasterNumLevels(Raster *raster)
{
return GETGL1RASTEREXT(raster)->numLevels;
}
// 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);
// Perhaps non-power-of-2 textures are acceptable?
width = img->width;
height = img->height;
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;
void (*conv)(uint8 *out, uint8 *in) = nil;
// 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->unpalettize();
image = truecolimg;
}
Gl1Raster *natras = GETGL1RASTEREXT(raster);
int32 format = raster->format&0xF00;
assert(!natras->isCompressed);
switch(image->depth){
case 32:
if(format == Raster::C8888)
conv = conv_RGBA8888_from_RGBA8888;
else if(format == Raster::C888)
conv = conv_RGB888_from_RGB888;
else
goto err;
break;
case 24:
if(format == Raster::C8888)
conv = conv_RGBA8888_from_RGB888;
else if(format == Raster::C888)
conv = conv_RGB888_from_RGB888;
else
goto err;
break;
case 16:
if(format == Raster::C8888)
conv = conv_RGBA8888_from_ARGB1555;
else if(format == Raster::C1555)
conv = conv_RGBA5551_from_ARGB1555;
else
goto err;
break;
case 8:
case 4:
default:
err:
RWERROR((ERR_INVRASTER));
return 0;
}
natras->hasAlpha = image->hasAlpha();
bool unlock = false;
if(raster->pixels == nil){
raster->lock(0, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
unlock = true;
}
uint8 *pixels = raster->pixels;
assert(pixels);
uint8 *imgpixels = image->pixels + (image->height-1)*image->stride;
int x, y;
assert(image->width == raster->width);
assert(image->height == raster->height);
for(y = 0; y < image->height; y++){
uint8 *imgrow = imgpixels;
uint8 *rasrow = pixels;
for(x = 0; x < image->width; x++){
conv(rasrow, imgrow);
imgrow += image->bpp;
rasrow += natras->bpp;
}
imgpixels -= image->stride;
pixels += raster->stride;
}
if(unlock)
raster->unlock(0);
if(truecolimg)
truecolimg->destroy();
return 1;
}
Image*
rasterToImage(Raster *raster)
{
int32 depth;
Image *image;
bool unlock = false;
if(raster->pixels == nil){
raster->lock(0, Raster::LOCKREAD);
unlock = true;
}
Gl1Raster *natras = GETGL1RASTEREXT(raster);
if(natras->isCompressed){
// TODO
RWERROR((ERR_INVRASTER));
return nil;
}
void (*conv)(uint8 *out, uint8 *in) = nil;
switch(raster->format & 0xF00){
case Raster::C1555:
depth = 16;
conv = conv_ARGB1555_from_RGBA5551;
break;
case Raster::C8888:
depth = 32;
conv = conv_RGBA8888_from_RGBA8888;
break;
case Raster::C888:
depth = 24;
conv = conv_RGB888_from_RGB888;
break;
default:
case Raster::C555:
case Raster::C565:
case Raster::C4444:
case Raster::LUM8:
RWERROR((ERR_INVRASTER));
return nil;
}
if(raster->format & Raster::PAL4 ||
raster->format & Raster::PAL8){
RWERROR((ERR_INVRASTER));
return nil;
}
uint8 *in, *out;
image = Image::create(raster->width, raster->height, depth);
image->allocate();
uint8 *imgpixels = image->pixels + (image->height-1)*image->stride;
uint8 *pixels = raster->pixels;
int x, y;
assert(image->width == raster->width);
assert(image->height == raster->height);
for(y = 0; y < image->height; y++){
uint8 *imgrow = imgpixels;
uint8 *rasrow = pixels;
for(x = 0; x < image->width; x++){
conv(imgrow, rasrow);
imgrow += image->bpp;
rasrow += natras->bpp;
}
imgpixels -= image->stride;
pixels += raster->stride;
}
if(unlock)
raster->unlock(0);
return image;
}
static void*
createNativeRaster(void *object, int32 offset, int32)
{
Gl1Raster *ras = PLUGINOFFSET(Gl1Raster, object, offset);
ras->texid = 0;
ras->fbo = 0;
ras->fboMate = nil;
ras->backingStore = nil;
return object;
}
void evictRaster(Raster *raster);
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
Raster *raster = (Raster*)object;
Gl1Raster *natras = PLUGINOFFSET(Gl1Raster, object, offset);
#ifdef RW_GLES1
evictRaster(raster);
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
glDeleteTextures(1, &natras->texid);
break;
case Raster::CAMERATEXTURE:
break;
case Raster::ZBUFFER:
break;
case Raster::CAMERA:
if(natras->fboMate){
// Break apart from currently associated zbuffer
Gl1Raster *zras = GETGL1RASTEREXT(natras->fboMate);
zras->fboMate = nil;
natras->fboMate = nil;
}
break;
}
natras->texid = 0;
natras->fbo = 0;
free(natras->backingStore);
#endif
return object;
}
static void*
copyNativeRaster(void *dst, void *, int32 offset, int32)
{
Gl1Raster *d = PLUGINOFFSET(Gl1Raster, dst, offset);
d->texid = 0;
d->fbo = 0;
d->fboMate = nil;
d->backingStore = nil;
return dst;
}
Texture*
readNativeTexture(Stream *stream)
{
uint32 platform;
if(!findChunk(stream, ID_STRUCT, nil, nil)){
RWERROR((ERR_CHUNK, "STRUCT"));
return nil;
}
platform = stream->readU32();
if(platform != PLATFORM_GLES1){
RWERROR((ERR_PLATFORM, platform));
return nil;
}
Texture *tex = Texture::create(nil);
if(tex == nil)
return nil;
// Texture
tex->filterAddressing = stream->readU32();
stream->read8(tex->name, 32);
stream->read8(tex->mask, 32);
// Raster
uint32 format = stream->readU32();
int32 width = stream->readI32();
int32 height = stream->readI32();
int32 depth = stream->readI32();
int32 numLevels = stream->readI32();
// Native raster
int32 subplatform = stream->readI32();
int32 flags = stream->readI32();
int32 compression = stream->readI32();
Raster *raster;
Gl1Raster *natras;
if(flags & 2){
tex->destroy();
RWERROR((ERR_FORMAT_UNSUPPORTED));
return nil;
}else{
raster = Raster::create(width, height, depth, format | Raster::TEXTURE, PLATFORM_GLES1);
}
assert(raster);
natras = GETGL1RASTEREXT(raster);
tex->raster = raster;
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = stream->readU32();
data = raster->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH);
stream->read8(data, size);
raster->unlock(i);
}
return tex;
}
void
writeNativeTexture(Texture *tex, Stream *stream)
{
Raster *raster = tex->raster;
Gl1Raster *natras = GETGL1RASTEREXT(raster);
int32 chunksize = getSizeNativeTexture(tex);
writeChunkHeader(stream, ID_STRUCT, chunksize-12);
stream->writeU32(PLATFORM_GLES1);
// Texture
stream->writeU32(tex->filterAddressing);
stream->write8(tex->name, 32);
stream->write8(tex->mask, 32);
// Raster
int32 numLevels = natras->numLevels;
stream->writeI32(raster->format);
stream->writeI32(raster->width);
stream->writeI32(raster->height);
stream->writeI32(raster->depth);
stream->writeI32(numLevels);
// Native raster
int32 flags = 0;
int32 compression = 0;
if(natras->hasAlpha)
flags |= 1;
if(natras->isCompressed){
flags |= 2;
switch(natras->internalFormat){
#ifdef RW_OPENGL
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
compression = 1;
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
compression = 3;
break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
compression = 5;
break;
#endif
default:
assert(0 && "unknown compression");
}
}
stream->writeI32(1);
stream->writeI32(flags);
stream->writeI32(compression);
// TODO: auto mipmaps?
uint32 size;
uint8 *data;
for(int32 i = 0; i < numLevels; i++){
size = getLevelSize(raster, i);
stream->writeU32(size);
data = raster->lock(i, Raster::LOCKREAD);
stream->write8(data, size);
raster->unlock(i);
}
}
uint32
getSizeNativeTexture(Texture *tex)
{
uint32 size = 12 + 72 + 32;
int32 levels = tex->raster->getNumLevels();
for(int32 i = 0; i < levels; i++)
size += 4 + getLevelSize(tex->raster, i);
return size;
}
void registerNativeRaster(void)
{
nativeRasterOffset = Raster::registerPlugin(sizeof(Gl1Raster),
ID_RASTERGLES1,
createNativeRaster,
destroyNativeRaster,
copyNativeRaster);
}
}
}

143
vendor/librw/src/gles1/gl1render.cpp vendored Normal file
View file

@ -0,0 +1,143 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwrender.h"
#include "../rwengine.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#ifdef RW_GLES1
#include "rwgles1.h"
#include "rwgles1impl.h"
namespace rw {
namespace gles1 {
#define MAX_LIGHTS
void
drawInst_simple(InstanceDataHeader *header, InstanceData *inst)
{
flushCache();
glDrawElements(header->primType, inst->numIndex,
GL_UNSIGNED_SHORT, (void*)(uintptr)inst->offset);
}
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void
drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst)
{
uint32 hasAlpha;
int alphafunc, alpharef, gsalpharef;
int zwrite;
hasAlpha = getAlphaBlend();
if(hasAlpha){
zwrite = rw::GetRenderState(rw::ZWRITEENABLE);
alphafunc = rw::GetRenderState(rw::ALPHATESTFUNC);
if(zwrite){
alpharef = rw::GetRenderState(rw::ALPHATESTREF);
gsalpharef = rw::GetRenderState(rw::GSALPHATESTREF);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAGREATEREQUAL);
SetRenderState(rw::ALPHATESTREF, gsalpharef);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHALESS);
SetRenderState(rw::ZWRITEENABLE, 0);
drawInst_simple(header, inst);
SetRenderState(rw::ZWRITEENABLE, 1);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
SetRenderState(rw::ALPHATESTREF, alpharef);
}else{
SetRenderState(rw::ALPHATESTFUNC, rw::ALPHAALWAYS);
drawInst_simple(header, inst);
SetRenderState(rw::ALPHATESTFUNC, alphafunc);
}
}else
drawInst_simple(header, inst);
}
void
drawInst(InstanceDataHeader *header, InstanceData *inst)
{
// if(rw::GetRenderState(rw::GSALPHATEST))
// drawInst_GSemu(header, inst);
// else
drawInst_simple(header, inst);
}
void
setupVertexInput(InstanceDataHeader *header)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, header->ibo);
glBindBuffer(GL_ARRAY_BUFFER, header->vbo);
}
void
teardownVertexInput(InstanceDataHeader *header)
{
}
int32
lightingCB(Atomic *atomic)
{
WorldLights lightData;
Light *directionals[8];
Light *locals[8];
lightData.directionals = directionals;
lightData.numDirectionals = 0; // 8;
lightData.locals = locals;
lightData.numLocals = 0; // 8;
if(atomic->geometry->flags & rw::Geometry::LIGHT){
((World*)engine->currentWorld)->enumerateLights(atomic, &lightData);
if((atomic->geometry->flags & rw::Geometry::NORMALS) == 0){
// Get rid of lights that need normals when we don't have any
lightData.numDirectionals = 0;
lightData.numLocals = 0;
}
return setLights(&lightData);
}else{
memset(&lightData, 0, sizeof(lightData));
return setLights(&lightData);
}
}
void
defaultRenderCB(Atomic *atomic, InstanceDataHeader *header)
{
Material *m;
uint32 flags = atomic->geometry->flags;
setWorldMatrix(atomic->getFrame()->getLTM());
int32 vsBits = lightingCB(atomic);
setupVertexInput(header);
InstanceData *inst = header->inst;
int32 n = header->numMeshes;
while(n--){
m = inst->material;
setMaterial(flags, m->color, m->surfaceProps);
setTexture(0, m->texture);
rw::SetRenderState(VERTEXALPHA, inst->vertexAlpha || m->color.alpha != 0xFF);
drawInst(header, inst);
inst++;
}
teardownVertexInput(header);
}
}
}
#endif

View file

@ -1,58 +0,0 @@
#include "rwgles1.h"
#ifdef RW_GLES1
namespace rw {
namespace gles1 {
// --- Funciones dummy (para linkear después) ---
inline void im2DRenderPrimitive(int, void*, int) {}
inline void im2DRenderIndexedPrimitive(int, void*, int, void*, int) {}
inline void im3DTransform(void*, int, void*, unsigned int) {}
inline void im3DRenderPrimitive(int) {}
inline void im3DRenderIndexedPrimitive(int, void*, int) {}
inline void im3DEnd(void) {}
// --- Driver lifecycle ---
static void*
driverOpen(void* object, int32 offset, int32 size)
{
// stub: no hace nada
return object;
}
static void*
driverClose(void* object, int32 offset, int32 size)
{
// stub: no hace nada
return object;
}
// --- Raster ---
static void
registerNativeRaster(void)
{
// stub por ahora
}
void
registerPlatformPlugins(void)
{
Driver::registerPlugin(PLATFORM_GLES1, 0, PLATFORM_GLES1,
driverOpen, driverClose);
registerNativeRaster();
}
void*
destroyNativeData(void *object, int32, int32)
{
//freeInstanceData((Geometry*)object);
return object;
}
}
}
#endif

View file

@ -1,28 +1,7 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "../rwbase.h"
#include "../rwerror.h"
#include "../rwplg.h"
#include "../rwpipeline.h"
#include "../rwobjects.h"
#include "../rwengine.h"
#ifdef RW_GLES1 #ifdef RW_GLES1
#include <GLES/gl.h> #include <gles/gl.h>
#include <GLES/egl.h> #include <gles/glext.h>
#ifdef __SYMBIAN32__ #include <gles/egl.h>
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
#endif #endif
namespace rw { namespace rw {
@ -30,79 +9,245 @@ namespace rw {
#ifdef RW_GLES1 #ifdef RW_GLES1
struct EngineOpenParams struct EngineOpenParams
{ {
int width, height; int width, height;
const char *windowtitle; const char *windowtitle;
}; };
#endif #endif
namespace gles1 { namespace gles1 {
// --- Tipos básicos que charset.cpp y otros esperan ---
struct Im2DVertex {
float x, y, z, w;
float camZ;
float recipCamZ;
unsigned char r, g, b, a;
float u, v;
// --- setters esperados por librw ---
void setScreenX(float v) { x = v; }
void setScreenY(float v) { y = v; }
void setScreenZ(float v) { z = v; }
void setCameraZ(float v) { camZ = v; }
void setRecipCameraZ(float v) { recipCamZ = v; }
void setColor(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a) {
r = _r; g = _g; b = _b; a = _a;
}
void setU(float val, float recipZ) { u = val; }
void setV(float val, float recipZ) { v = val; }
};
struct Im3DVertex {
float x, y, z;
float u, v;
uint32 color;
void setX(float v) { x = v; }
void setY(float v) { y = v; }
void setZ(float v) { z = v; }
void setU(float v) { u = v; }
void setV(float v) { this->v = v; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
color = (a<<24) | (r<<16) | (g<<8) | b;
}
};
// --- Funciones dummy (para linkear después) ---
inline void im2DRenderPrimitive(int, void*, int);
inline void im2DRenderIndexedPrimitive(int, void*, int, void*, int);
inline void im3DTransform(void*, int, void*, unsigned int);
inline void im3DRenderPrimitive(int);
inline void im3DRenderIndexedPrimitive(int, void*, int);
inline void im3DEnd(void);
// --- Driver lifecycle ---
static void*
driverOpen(void* object, int32 offset, int32 size);
static void*
driverClose(void* object, int32 offset, int32 size);
// --- Raster ---
static void
registerNativeRaster(void);
void registerPlatformPlugins(void); void registerPlatformPlugins(void);
extern Device renderdevice;
// arguments to glVertexAttribPointer basically
struct AttribDesc
{
uint32 index;
int32 type;
bool32 normalized;
int32 size;
uint32 stride;
uint32 offset;
};
enum AttribIndices
{
ATTRIB_POS = 0,
ATTRIB_NORMAL,
ATTRIB_COLOR,
ATTRIB_WEIGHTS,
ATTRIB_INDICES,
ATTRIB_TEXCOORDS0,
ATTRIB_TEXCOORDS1,
#if 0
ATTRIB_TEXCOORDS2,
ATTRIB_TEXCOORDS3,
ATTRIB_TEXCOORDS4,
ATTRIB_TEXCOORDS5,
ATTRIB_TEXCOORDS6,
ATTRIB_TEXCOORDS7,
#endif
};
// default uniform indices
extern int32 u_matColor;
extern int32 u_surfProps;
struct InstanceData
{
uint32 numIndex;
uint32 minVert; // not used for rendering
int32 numVertices; //
Material *material;
bool32 vertexAlpha;
uint32 program;
uint32 offset;
};
struct InstanceDataHeader : rw::InstanceDataHeader
{
uint32 serialNumber;
uint32 numMeshes;
uint16 *indexBuffer;
uint32 primType;
uint8 *vertexBuffer;
int32 numAttribs;
AttribDesc *attribDesc;
uint32 totalNumIndex;
uint32 totalNumVertex;
uint32 ibo;
uint32 vbo; // or 2?
InstanceData *inst;
};
#ifdef RW_GLES1
struct Im3DVertex
{
V3d position;
uint8 r, g, b, a;
float32 u, v;
void setX(float32 x) { this->position.x = x; }
void setY(float32 y) { this->position.y = y; }
void setZ(float32 z) { this->position.z = z; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
this->r = r; this->g = g; this->b = b; this->a = a; }
void setU(float32 u) { this->u = u; }
void setV(float32 v) { this->v = v; }
float getX(void) { return this->position.x; }
float getY(void) { return this->position.y; }
float getZ(void) { return this->position.z; }
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
float getU(void) { return this->u; }
float getV(void) { return this->v; }
};
struct Im2DVertex
{
float32 x, y, z, w;
uint8 r, g, b, a;
float32 u, v;
void setScreenX(float32 x) { this->x = x; }
void setScreenY(float32 y) { this->y = y; }
void setScreenZ(float32 z) { this->z = z; }
// This is a bit unefficient but we have to counteract GL's divide, so multiply
void setCameraZ(float32 z) { this->w = z; }
void setRecipCameraZ(float32 recipz) { this->w = 1.0f/recipz; }
void setColor(uint8 r, uint8 g, uint8 b, uint8 a) {
this->r = r; this->g = g; this->b = b; this->a = a; }
void setU(float32 u, float recipz) { this->u = u; }
void setV(float32 v, float recipz) { this->v = v; }
float getScreenX(void) { return this->x; }
float getScreenY(void) { return this->y; }
float getScreenZ(void) { return this->z; }
float getCameraZ(void) { return this->w; }
float getRecipCameraZ(void) { return 1.0f/this->w; }
RGBA getColor(void) { return makeRGBA(this->r, this->g, this->b, this->a); }
float getU(void) { return this->u; }
float getV(void) { return this->v; }
};
void setupVertexInput(InstanceDataHeader *header);
void teardownVertexInput(InstanceDataHeader *header);
// Render state
// Vertex shader bits
enum
{
// These should be low so they could be used as indices
VSLIGHT_DIRECT = 1,
VSLIGHT_POINT = 2,
VSLIGHT_SPOT = 4,
VSLIGHT_MASK = 7, // all the above
// less critical
VSLIGHT_AMBIENT = 8,
};
// per Scene
void setProjectionMatrix(float32*);
void setViewMatrix(float32*);
// per Object
void setWorldMatrix(Matrix*);
int32 setLights(WorldLights *lightData);
// per Mesh
void setTexture(int32 n, Texture *tex);
void setMaterial(const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f);
inline void setMaterial(uint32 flags, const RGBA &color, const SurfaceProperties &surfaceprops, float extraSurfProp = 0.0f)
{
static RGBA white = { 255, 255, 255, 255 };
if(flags & Geometry::MODULATE)
setMaterial(color, surfaceprops, extraSurfProp);
else
setMaterial(white, surfaceprops, extraSurfProp);
}
void setAlphaBlend(bool32 enable);
bool32 getAlphaBlend(void);
bool32 getAlphaTest(void);
void bindFramebuffer(uint32 fbo);
uint32 bindTexture(uint32 texid);
void flushCache(void);
#endif
class ObjPipeline : public rw::ObjPipeline
{
public:
void init(void);
static ObjPipeline *create(void);
void (*instanceCB)(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
void (*uninstanceCB)(Geometry *geo, InstanceDataHeader *header);
void (*renderCB)(Atomic *atomic, InstanceDataHeader *header);
};
void defaultInstanceCB(Geometry *geo, InstanceDataHeader *header, bool32 reinstance);
void defaultUninstanceCB(Geometry *geo, InstanceDataHeader *header);
void defaultRenderCB(Atomic *atomic, InstanceDataHeader *header);
int32 lightingCB(Atomic *atomic);
void drawInst_simple(InstanceDataHeader *header, InstanceData *inst);
// Emulate PS2 GS alpha test FB_ONLY case: failed alpha writes to frame- but not to depth buffer
void drawInst_GSemu(InstanceDataHeader *header, InstanceData *inst);
// This one switches between the above two depending on render state;
void drawInst(InstanceDataHeader *header, InstanceData *inst);
void *destroyNativeData(void *object, int32, int32); void *destroyNativeData(void *object, int32, int32);
ObjPipeline *makeDefaultPipeline(void);
// Native Texture and Raster
struct Gl1Raster
{
// arguments to glTexImage2D
int32 internalFormat;
int32 type;
int32 format;
int32 bpp; // bytes per pixel
// texture object
uint32 texid;
bool isCompressed;
bool hasAlpha;
bool autogenMipmap;
int8 numLevels;
// cached filtermode and addressing
uint8 filterMode;
uint8 addressU;
uint8 addressV;
int32 maxAnisotropy;
uint32 fbo; // used for camera texture only!
Raster *fboMate; // color or zbuffer raster mate of this one
RasterLevels *backingStore; // if we can't read back GPU memory but have to
};
// GLES can't read back textures very nicely.
// In most cases that's not an issue, but when it is,
// this has to be set before the texture is filled:
extern bool32 needToReadBackTextures;
Texture *readNativeTexture(Stream *stream);
void writeNativeTexture(Texture *tex, Stream *stream);
uint32 getSizeNativeTexture(Texture *tex);
extern int32 nativeRasterOffset;
void registerNativeRaster(void);
#define GETGL1RASTEREXT(raster) PLUGINOFFSET(Gl1Raster, raster, rw::gles1::nativeRasterOffset)
} }
} }

83
vendor/librw/src/gles1/rwgles1impl.h vendored Normal file
View file

@ -0,0 +1,83 @@
namespace rw {
namespace gles1 {
#ifdef RW_GLES1
extern uint32 im2DVbo, im2DIbo;
void openIm2D(void);
void closeIm2D(void);
void im2DRenderLine(void *vertices, int32 numVertices,
int32 vert1, int32 vert2);
void im2DRenderTriangle(void *vertices, int32 numVertices,
int32 vert1, int32 vert2, int32 vert3);
void im2DRenderPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices);
void im2DRenderIndexedPrimitive(PrimitiveType primType,
void *vertices, int32 numVertices, void *indices, int32 numIndices);
void openIm3D(void);
void closeIm3D(void);
void im3DTransform(void *vertices, int32 numVertices, Matrix *world, uint32 flags);
void im3DRenderPrimitive(PrimitiveType primType);
void im3DRenderIndexedPrimitive(PrimitiveType primType, void *indices, int32 numIndices);
void im3DEnd(void);
struct DisplayMode
{
#ifdef __SYMBIAN32__
uint32 width;
uint32 height;
#else
#ifdef LIBRW_SDL2
SDL_DisplayMode mode;
#else
GLFWvidmode mode;
#endif
#endif
int32 depth;
uint32 flags;
};
struct GlGlobals
{
#ifdef LIBRW_SDL2
SDL_Window **pWindow;
SDL_Window *window;
SDL_GLContext glcontext;
#else
#ifndef __SYMBIAN32__
GLFWwindow **pWindow;
GLFWwindow *window;
GLFWmonitor *monitor;
#endif
int numMonitors;
int currentMonitor;
#endif
DisplayMode *modes;
int numModes;
int currentMode;
int presentWidth, presentHeight;
int presentOffX, presentOffY;
// for opening the window
int winWidth, winHeight;
const char *winTitle;
uint32 numSamples;
};
extern GlGlobals glGlobals;
#endif
Raster *rasterCreate(Raster *raster);
uint8 *rasterLock(Raster*, int32 level, int32 lockMode);
void rasterUnlock(Raster*, int32);
int32 rasterNumLevels(Raster*);
bool32 imageFindRasterFormat(Image *img, int32 type,
int32 *width, int32 *height, int32 *depth, int32 *format);
bool32 rasterFromImage(Raster *raster, Image *image);
Image *rasterToImage(Raster *raster);
}
}

View file

@ -626,6 +626,7 @@ enum PluginID
ID_RASTERD3D9 = MAKEPLUGINID(VEND_RASTER, PLATFORM_D3D9), ID_RASTERD3D9 = MAKEPLUGINID(VEND_RASTER, PLATFORM_D3D9),
ID_RASTERWDGL = MAKEPLUGINID(VEND_RASTER, PLATFORM_WDGL), ID_RASTERWDGL = MAKEPLUGINID(VEND_RASTER, PLATFORM_WDGL),
ID_RASTERGL3 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GL3), ID_RASTERGL3 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GL3),
ID_RASTERGLES1 = MAKEPLUGINID(VEND_RASTER, PLATFORM_GLES1),
// anything driver/device related (only as allocation tag) // anything driver/device related (only as allocation tag)
ID_DRIVER = MAKEPLUGINID(VEND_DRIVER, 0) ID_DRIVER = MAKEPLUGINID(VEND_DRIVER, 0)

View file

@ -17,6 +17,7 @@
#include "d3d/rwd3d9.h" #include "d3d/rwd3d9.h"
#include "d3d/rwd3dimpl.h" #include "d3d/rwd3dimpl.h"
#include "gl/rwgl3.h" #include "gl/rwgl3.h"
#include "gles1/rwgles1.h"
#define PLUGIN_ID 0 #define PLUGIN_ID 0
@ -482,8 +483,8 @@ Texture::streamReadNative(Stream *stream)
if(platform == PLATFORM_GL3) if(platform == PLATFORM_GL3)
return gl3::readNativeTexture(stream); return gl3::readNativeTexture(stream);
#ifdef RW_GLES1 #ifdef RW_GLES1
// if(platform == PLATFORM_GLES1) // TODO if(platform == PLATFORM_GLES1)
// return gles1::readNativeTexture(stream); return gles1::readNativeTexture(stream);
#endif #endif
assert(0 && "unsupported platform"); assert(0 && "unsupported platform");
return nil; return nil;
@ -503,8 +504,8 @@ Texture::streamWriteNative(Stream *stream)
else if(this->raster->platform == PLATFORM_GL3) else if(this->raster->platform == PLATFORM_GL3)
gl3::writeNativeTexture(this, stream); gl3::writeNativeTexture(this, stream);
#ifdef RW_GLES1 #ifdef RW_GLES1
// else if(this->raster->platform == PLATFORM_GLES1) else if(this->raster->platform == PLATFORM_GLES1)
// gles1::writeNativeTexture(this, stream); gles1::writeNativeTexture(this, stream);
#endif #endif
else else
assert(0 && "unsupported platform"); assert(0 && "unsupported platform");
@ -524,8 +525,8 @@ Texture::streamGetSizeNative(void)
if(this->raster->platform == PLATFORM_GL3) if(this->raster->platform == PLATFORM_GL3)
return gl3::getSizeNativeTexture(this); return gl3::getSizeNativeTexture(this);
#ifdef RW_GLES1 #ifdef RW_GLES1
// if(this->raster->platform == PLATFORM_GLES1) if(this->raster->platform == PLATFORM_GLES1)
// return gles1::getSizeNativeTexture(this); return gles1::getSizeNativeTexture(this);
#endif #endif
assert(0 && "unsupported platform"); assert(0 && "unsupported platform");
return 0; return 0;