diff --git a/desmume/src/OGLRender.cpp b/desmume/src/OGLRender.cpp index 97ac437e4..a781c731e 100644 --- a/desmume/src/OGLRender.cpp +++ b/desmume/src/OGLRender.cpp @@ -99,7 +99,8 @@ static u32 textureFormat=0, texturePalette=0; // ClearImage/Rear-plane (FBO) GLenum oglClearImageTextureID[2] = {0}; // 0 - image, 1 - depth -GLuint oglClearImageBuffers[2] = {0}; // 0 - image, 1 - depth +GLuint oglClearImageBuffers = 0; +GLuint oglClearImageRender[1] = {0}; bool oglFBOdisabled = false; u32 *oglClearImageColor = NULL; float *oglClearImageDepth = NULL; @@ -144,7 +145,6 @@ OGLEXT(PFNGLUNIFORM1IVPROC,glUniform1iv) // FBO OGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC,glGenFramebuffersEXT); OGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC,glBindFramebufferEXT); -OGLEXT(PFNGLRENDERBUFFERSTORAGEEXTPROC,glRenderbufferStorageEXT); OGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC,glFramebufferRenderbufferEXT); OGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC,glFramebufferTexture2DEXT); OGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC,glCheckFramebufferStatusEXT); @@ -280,8 +280,8 @@ GLuint vertexShaderID; GLuint fragmentShaderID; GLuint shaderProgram; -static GLuint hasTexLoc; -static GLuint texBlendLoc; +static GLint hasTexLoc; +static GLint texBlendLoc; static bool hasTexture = false; static TexCacheItem* currTexture = NULL; @@ -356,7 +356,7 @@ static void OGLReset() glUniform1i(hasTexLoc, 0); hasTexture = false; glUniform1i(texBlendLoc, 0); - + } TexCache_Reset(); @@ -367,10 +367,10 @@ static void OGLReset() // memset(GPU_screenStencil,0,sizeof(GPU_screenStencil)); memset(GPU_screen3D,0,sizeof(GPU_screen3D)); - memset(oglClearImageColor, 0, 256*192); - memset(oglClearImageDepth, 0, 256*192); - memset(oglClearImageColorTemp, 0, 256*192*2); - memset(oglClearImageDepthTemp, 0, 256*192*2); + memset(oglClearImageColor, 0, 256*192*sizeof(u32)); + memset(oglClearImageDepth, 0, 256*192*sizeof(float)); + memset(oglClearImageColorTemp, 0, 256*192*sizeof(u16)); + memset(oglClearImageDepthTemp, 0, 256*192*sizeof(u16)); oglClearImageScrollOld = 0; } @@ -418,7 +418,7 @@ static void expandFreeTextures() static char OGLInit(void) { - GLuint loc = 0; + GLint loc = 0; if(!oglrender_init) return 0; @@ -468,7 +468,6 @@ static char OGLInit(void) // FBO INITOGLEXT(PFNGLGENFRAMEBUFFERSEXTPROC,glGenFramebuffersEXT); INITOGLEXT(PFNGLBINDFRAMEBUFFEREXTPROC,glBindFramebufferEXT); - INITOGLEXT(PFNGLRENDERBUFFERSTORAGEEXTPROC,glRenderbufferStorageEXT); INITOGLEXT(PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC,glFramebufferRenderbufferEXT); INITOGLEXT(PFNGLFRAMEBUFFERTEXTURE2DEXTPROC,glFramebufferTexture2DEXT); INITOGLEXT(PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC,glCheckFramebufferStatusEXT); @@ -540,22 +539,19 @@ static char OGLInit(void) glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); // FBO oglFBOdisabled = false; - glGenFramebuffersEXT(2, &oglClearImageBuffers[0]); + glGenFramebuffersEXT(1, &oglClearImageBuffers); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oglClearImageBuffers[0]); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oglClearImageBuffers); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, oglClearImageTextureID[0], 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oglClearImageBuffers[1]); - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); + //glDrawBuffer(GL_NONE); + //glReadBuffer(GL_NONE); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, oglClearImageTextureID[1], 0); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)==GL_FRAMEBUFFER_COMPLETE_EXT) INFO("Successfully created OpenGL Framebuffer object (FBO)\n"); else @@ -564,15 +560,12 @@ static char OGLInit(void) oglFBOdisabled = true; } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + oglClearImageColor = new u32[256*192]; oglClearImageColorTemp = new u16[256*192]; oglClearImageDepth = new float[256*192]; oglClearImageDepthTemp = new u16[256*192]; - memset(oglClearImageColor, 0, 256*192); - memset(oglClearImageDepth, 0, 256*192); - memset(oglClearImageColorTemp, 0, 256*192); - memset(oglClearImageDepthTemp, 0, 256*192); - oglClearImageScrollOld = 0; glActiveTexture(GL_TEXTURE0); @@ -617,7 +610,7 @@ static void OGLClose() // FBO glDeleteTextures(2, &oglClearImageTextureID[0]); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glDeleteFramebuffersEXT(2, &oglClearImageBuffers[0]); + glDeleteFramebuffersEXT(1, &oglClearImageBuffers); if (oglClearImageColor) { @@ -969,7 +962,8 @@ static void oglClearImageFBO() u16 col = clearImage[adr]; oglClearImageColor[dd] = RGB15TO32(col,255*(col>>15)); - u32 depth = clearDepth[adr] & 0x7FFF; + u16 depth = clearDepth[adr] & 0x7FFF; + if (depth == 0x7FFF) oglClearImageDepth[dd] = 1.f; else @@ -986,19 +980,16 @@ static void oglClearImageFBO() // depth glBindTexture(GL_TEXTURE_2D, oglClearImageTextureID[1]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &oglClearImageDepth[0]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 256, 192, 0, GL_DEPTH_COMPONENT, GL_FLOAT, &oglClearImageDepth[0]); glActiveTexture(GL_TEXTURE0); } - // color - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oglClearImageBuffers[0]); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); - glBlitFramebufferEXT(0,0,256,192,0,0,256,192,GL_COLOR_BUFFER_BIT,GL_LINEAR); - // depth - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oglClearImageBuffers[1]); - glBlitFramebufferEXT(0,0,256,192,0,0,256,192,GL_DEPTH_BUFFER_BIT,GL_LINEAR); + // color & depth + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oglClearImageBuffers); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBlitFramebufferEXT(0,0,256,192,0,0,256,192,GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT,GL_LINEAR); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); @@ -1094,15 +1085,26 @@ static void OGLRender() float alpha = poly->getAlpha()/31.0f; if(wireframe) alpha = 1.0; + +#ifdef _NEW_VTX + GLenum dd[] = {GL_TRIANGLES, GL_QUADS, GL_TRIANGLE_STRIP, GL_QUAD_STRIP, + GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP}; + glBegin(dd[type]); + + for(int j = 0; j < poly->vertCount; j++) + { +#else if (gfx3d_IsLinePoly(poly)) glBegin(GL_LINE_LOOP); else if (type == 4) glBegin(GL_QUADS); else glBegin(GL_TRIANGLES); - + + for(int j = 0; j < type; j++) { +#endif VERT *vert = &gfx3d.vertlist->list[poly->vertIndexes[j]]; glTexCoord2fv(vert->texcoord); diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 9ab8199ba..f5c482675 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -47,6 +47,13 @@ #include "movie.h" //only for currframecounter which really ought to be moved into the core emu.... #include +//#define _SHOW_VTX_COUNTERS // show polygon/vertex counters on screen +#ifdef _SHOW_VTX_COUNTERS +u32 max_polys, max_verts; +#include "GPU_OSD.h" +#endif + + /* thoughts on flush timing: I think a flush is supposed to queue up and wait to happen during vblank sometime. @@ -368,7 +375,7 @@ BOOL isSwapBuffers = FALSE; static u32 BTind = 0; static u32 PTind = 0; -static u16 BTcoords[6] = {0, 0, 0, 0, 0, 0}; +static CACHE_ALIGN u16 BTcoords[6] = {0, 0, 0, 0, 0, 0}; static CACHE_ALIGN float PTcoords[4] = {0.0, 0.0, 0.0, 1.0}; //raw ds format poly attributes @@ -432,6 +439,9 @@ static void twiddleLists() { vertlist = &vertlists[listTwiddle]; polylist->count = 0; vertlist->count = 0; +#ifdef _NEW_VTX + polylist->resetVertCounts(); +#endif } static BOOL flushPending = FALSE; @@ -503,6 +513,10 @@ void gfx3d_init() void gfx3d_reset() { +#ifdef _SHOW_VTX_COUNTERS + max_polys = max_verts = 0; +#endif + reconstruct(&gfx3d); delete viewer3d_state; viewer3d_state = new Viewer3d_State(); @@ -535,7 +549,9 @@ void gfx3d_reset() memset(gxPIPE.cmd, 0, sizeof(gxPIPE.cmd)); memset(gxPIPE.param, 0, sizeof(gxPIPE.param)); memset(colorRGB, 0, sizeof(colorRGB)); +#ifndef _NEW_VTX memset(&tempVertInfo, 0, sizeof(tempVertInfo)); +#endif MatrixInit (mtxCurrent[0]); MatrixInit (mtxCurrent[1]); @@ -595,7 +611,114 @@ FORCEINLINE s32 vec3dot_fixed32(const s32* a, const s32* b) { return fx32_shiftdown(fx32_mul(a[0],b[0]) + fx32_mul(a[1],b[1]) + fx32_mul(a[2],b[2])); } +#ifdef _NEW_VTX +#define SUBMITVERTEX(ii, nn) polylist->list[polylist->count].vertIndexes[polylist->list[polylist->count].vertCount+ii] = vertIndex+nn; +static void SetVertex() +{ + s32 coord[3] = { + s16coord[0], + s16coord[1], + s16coord[2] + }; + ALIGN(16) s32 coordTransformed[4] = { coord[0], coord[1], coord[2], (1<<12) }; + + if (texCoordinateTransform == 3) + { + //Tested by: Eledees The Adventures of Kai and Zero (E) [title screen and frontend menus] + last_s = (s32)(((s64)s16coord[0] * mtxCurrent[3][0] + + (s64)s16coord[1] * mtxCurrent[3][4] + + (s64)s16coord[2] * mtxCurrent[3][8] + + (((s64)(_s))<<24))>>24); + last_t = (s32)(((s64)s16coord[0] * mtxCurrent[3][1] + + (s64)s16coord[1] * mtxCurrent[3][5] + + (s64)s16coord[2] * mtxCurrent[3][9] + + (((s64)(_t))<<24))>>24); + } + + //refuse to do anything if we have too many verts or polys + polygonListCompleted = 0; + if(vertlist->count >= VERTLIST_SIZE) + { + printf("!!! VERTEX overflow\n"); + return; + } + if(polylist->count >= POLYLIST_SIZE) + { + printf("!!! POLYGON overflow\n"); + return; + } + + //TODO - think about keeping the clip matrix concatenated, + //so that we only have to multiply one matrix here + //(we could lazy cache the concatenated clip matrix and only generate it + //when we need to) + MatrixMultVec4x4_M2(mtxCurrent[0], coordTransformed); + + //printf("%f %f %f\n",s16coord[0]/4096.0f,s16coord[1]/4096.0f,s16coord[2]/4096.0f); + //printf("x %f %f %f %f\n",mtxCurrent[0][0]/4096.0f,mtxCurrent[0][1]/4096.0f,mtxCurrent[0][2]/4096.0f,mtxCurrent[0][3]/4096.0f); + //printf(" = %f %f %f %f\n",coordTransformed[0]/4096.0f,coordTransformed[1]/4096.0f,coordTransformed[2]/4096.0f,coordTransformed[3]/4096.0f); + + //TODO - culling should be done here. + //TODO - viewport transform? + + //record the vertex + int vertIndex = vertlist->count; + if(vertIndex<0) { + printf("wtf\n"); + } + VERT &vert = vertlist->list[vertIndex]; + + //printf("%f %f %f\n",coordTransformed[0],coordTransformed[1],coordTransformed[2]); + //if(coordTransformed[1] > 20) + // coordTransformed[1] = 20; + + //printf("y-> %f\n",coord[1]); + + //if(mtxCurrent[1][14]>15) { + // printf("ACK!\n"); + // printf("----> modelview 1 state for that ack:\n"); + // //MatrixPrint(mtxCurrent[1]); + //} + + vert.texcoord[0] = last_s/16.0f; + vert.texcoord[1] = last_t/16.0f; + vert.coord[0] = coordTransformed[0]/4096.0f; + vert.coord[1] = coordTransformed[1]/4096.0f; + vert.coord[2] = coordTransformed[2]/4096.0f; + vert.coord[3] = coordTransformed[3]/4096.0f; + vert.color[0] = GFX3D_5TO6(colorRGB[0]); + vert.color[1] = GFX3D_5TO6(colorRGB[1]); + vert.color[2] = GFX3D_5TO6(colorRGB[2]); + + //possibly complete a polygon + { + switch(vtxFormat) { + case 0: //GL_TRIANGLES + case 2: //GL_TRIANGLE_STRIP + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); + SUBMITVERTEX(2,2); + vertlist->count+=3; + break; + case 1: //GL_QUADS + case 3: //GL_QUAD_STRIP + SUBMITVERTEX(0,0); + SUBMITVERTEX(1,1); + SUBMITVERTEX(2,2); + SUBMITVERTEX(3,3); + vertlist->count+=4; + break; + default: + printf("!!! Error VTX format (%i)\n", vtxFormat); + return; + } + + polylist->list[polylist->count].vertCount++; + polylist->list[polylist->count].type = vtxFormat; + } +} +#else #define SUBMITVERTEX(ii, nn) polylist->list[polylist->count].vertIndexes[ii] = tempVertInfo.map[nn]; //Submit a vertex to the GE static void SetVertex() @@ -763,6 +886,7 @@ static void SetVertex() } } } +#endif static void gfx3d_glPolygonAttrib_cache() { @@ -1384,8 +1508,10 @@ static void gfx3d_glBegin(u32 v) inBegin = TRUE; vtxFormat = v&0x03; triStripToggle = 0; +#ifndef _NEW_VTX tempVertInfo.count = 0; tempVertInfo.first = true; +#endif polyAttr = polyAttrPending; gfx3d_glPolygonAttrib_cache(); GFX_DELAY(1); @@ -1393,8 +1519,30 @@ static void gfx3d_glBegin(u32 v) static void gfx3d_glEnd(void) { - inBegin = FALSE; +#ifdef _NEW_VTX + if (inBegin) + { + POLY &poly = polylist->list[polylist->count]; + //printf("Poly %i: vert count %i\n", polylist->list[polylist->count].type, polylist->list[polylist->count].vertCount); + // TODO: line segments detect + u8 type = polylist->list[polylist->count].type; + if (gfx3d_IsLinePoly(&poly)) + { + printf("Poly %i: vert count %i - line detected\n", polylist->list[polylist->count].type, polylist->list[polylist->count].vertCount); + poly.type += 4; + } + + poly.polyAttr = polyAttr; + poly.texParam = textureFormat; + poly.texPalette = texturePalette; + poly.viewport = viewport; + polylist->count++; + } +#else tempVertInfo.count = 0; +#endif + inBegin = FALSE; + GFX_DELAY(1); } @@ -2055,6 +2203,12 @@ static void gfx3d_doFlush() gfx3d.state.activeFlushCommand = gfx3d.state.pendingFlushCommand; int polycount = polylist->count; +#ifdef _SHOW_VTX_COUNTERS + max_polys = max((u32)polycount, max_polys); + max_verts = max((u32)vertlist->count, max_verts); + osd->addFixed(10, 320, "%i/%i", polycount, vertlist->count); // current + osd->addFixed(10, 335, "%i/%i", max_polys, max_verts); // max +#endif //find the min and max y values for each poly. //TODO - this could be a small waste of time if we are manual sorting the translucent polys @@ -2363,9 +2517,11 @@ SFORMAT SF_GFX3D[]={ { "GSPF", 4, 1, &gfx3d.state.pendingFlushCommand}, //------------------------ { "GTST", 4, 1, &triStripToggle}, +#ifndef _NEW_VTX { "GTVC", 4, 1, &tempVertInfo.count}, { "GTVM", 4, 4, tempVertInfo.map}, { "GTVF", 4, 1, &tempVertInfo.first}, +#endif { "G3CX", 1, 4*256*192, gfx3d_convertedScreen}, { 0 } }; @@ -2804,6 +2960,10 @@ void GFX3D_Clipper::clipPoly(POLY* poly, VERT** verts) // "Workaround" for line poly bool gfx3d_IsLinePoly(POLY *poly) { +#ifdef _NEW_VTX + // TODO: + return false; +#else int type = poly->type; VERT *vert1, *vert2; @@ -2865,4 +3025,5 @@ bool gfx3d_IsLinePoly(POLY *poly) return true; return false; +#endif } diff --git a/desmume/src/gfx3d.h b/desmume/src/gfx3d.h index 05622c6a3..127385dc8 100644 --- a/desmume/src/gfx3d.h +++ b/desmume/src/gfx3d.h @@ -139,7 +139,12 @@ void gfx3d_reset(); struct POLY { int type; //tri or quad +#ifdef _NEW_VTX + u16 vertIndexes[2048]; + u16 vertCount; +#else u16 vertIndexes[4]; //up to four verts can be referenced by this poly +#endif u32 polyAttr, texParam, texPalette; //the hardware rendering params u32 viewport; float miny, maxy; @@ -191,11 +196,21 @@ struct POLY { } }; +#ifdef _NEW_VTX +#define POLYLIST_SIZE 2048 +#else #define POLYLIST_SIZE 100000 -//#define POLYLIST_SIZE 2048 +#endif struct POLYLIST { POLY list[POLYLIST_SIZE]; int count; +#ifdef _NEW_VTX + void resetVertCounts() + { + for (u16 i=0; i < POLYLIST_SIZE; i++) + list[i].vertCount = 0; + } +#endif }; struct VERT { diff --git a/desmume/src/rasterize.cpp b/desmume/src/rasterize.cpp index b6d2f3dfc..1bc38598f 100644 --- a/desmume/src/rasterize.cpp +++ b/desmume/src/rasterize.cpp @@ -1015,10 +1015,18 @@ public: //hmm... shader gets setup every time because it depends on sampler which may have just changed setupShader(poly->polyAttr); +#ifdef _NEW_VTX + // TODO: CrazyMax (9 Feb 2011): zeromus check it, please + for(int j=0;jvertCount;j++) + this->verts[j] = &clippedPoly.clipVerts[j]; + for(int j=poly->vertCount;jverts[j] = NULL; +#else for(int j=0;jverts[j] = &clippedPoly.clipVerts[j]; for(int j=type;jverts[j] = NULL; +#endif polyAttr.backfacing = engine->polyBackfacing[i]; diff --git a/desmume/src/windows/defaultconfig/userconfig.h b/desmume/src/windows/defaultconfig/userconfig.h index ede47cdc4..0375fc17c 100644 --- a/desmume/src/windows/defaultconfig/userconfig.h +++ b/desmume/src/windows/defaultconfig/userconfig.h @@ -16,5 +16,6 @@ //#define EXPERIMENTAL_WIFI_COMM //enables experimental wifi communication features which do not actually work yet //basic wifi register emulation is still enabled, to at least make it seem like the wifi is working in an empty universe +//#define _NEW_VTX // enables new 3D polygon definitions (experimental) #endif //_USERCONFIG_H