/* * Glide64 - Glide video plugin for Nintendo 64 emulators. * Copyright (c) 2002 Dave2001 * Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #ifdef _WIN32 #include #endif // _WIN32 #include "glide.h" #include "glitchmain.h" #include "../Glide64/winlnxdefs.h" #include "../Glide64/rdp.h" #define Z_MAX (65536.0f) #define VERTEX_SIZE sizeof(VERTEX) //Size of vertex struct #ifdef ANDROID_EDITION #include "ae_imports.h" static float polygonOffsetFactor; static float polygonOffsetUnits; #endif static int xy_off; static int xy_en; static int z_en; static int z_off; static int q_off; static int q_en; static int pargb_off; static int pargb_en; static int st0_off; static int st0_en; static int st1_off; static int st1_en; static int fog_ext_off; static int fog_ext_en; int w_buffer_mode; int inverted_culling; int culling_mode; #define VERTEX_BUFFER_SIZE 1500 //Max amount of vertices to buffer, this seems large enough. static VERTEX vertex_buffer[VERTEX_BUFFER_SIZE]; static int vertex_buffer_count = 0; static GLenum vertex_draw_mode; static bool vertex_buffer_enabled = false; void vbo_init() { } void vbo_draw() { if(vertex_buffer_count) { glDrawArrays(vertex_draw_mode,0,vertex_buffer_count); vertex_buffer_count = 0; } } //Buffer vertices instead of glDrawArrays(...) void vbo_buffer(GLenum mode,GLint first,GLsizei count,void* pointers) { if((count != 3 && mode != GL_TRIANGLES) || vertex_buffer_count + count > VERTEX_BUFFER_SIZE) { vbo_draw(); } memcpy(&vertex_buffer[vertex_buffer_count],pointers,count * VERTEX_SIZE); vertex_buffer_count += count; if(count == 3 || mode == GL_TRIANGLES) { vertex_draw_mode = GL_TRIANGLES; } else { vertex_draw_mode = mode; vbo_draw(); //Triangle fans and strips can't be joined as easily, just draw them straight away. } } void vbo_enable() { if(vertex_buffer_enabled) return; vertex_buffer_enabled = true; glEnableVertexAttribArray(POSITION_ATTR); glVertexAttribPointer(POSITION_ATTR, 4, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].x); //Position glEnableVertexAttribArray(COLOUR_ATTR); glVertexAttribPointer(COLOUR_ATTR, 4, GL_UNSIGNED_BYTE, true, VERTEX_SIZE, &vertex_buffer[0].b); //Colour glEnableVertexAttribArray(TEXCOORD_0_ATTR); glVertexAttribPointer(TEXCOORD_0_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[2]); //Tex0 glEnableVertexAttribArray(TEXCOORD_1_ATTR); glVertexAttribPointer(TEXCOORD_1_ATTR, 2, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].coord[0]); //Tex1 glEnableVertexAttribArray(FOG_ATTR); glVertexAttribPointer(FOG_ATTR, 1, GL_FLOAT, false, VERTEX_SIZE, &vertex_buffer[0].f); //Fog } void vbo_disable() { vbo_draw(); vertex_buffer_enabled = false; } inline float ZCALC(const float & z, const float & q) { float res = z_en ? ((z) / Z_MAX) / (q) : 1.0f; return res; } /* #define zclamp (1.0f-1.0f/zscale) static inline void zclamp_glVertex4f(float a, float b, float c, float d) { if (c 0.01f) continue; if (z < bestz) { bestz = z; biasFactor = f; } //printf("f %g z %g\n", f, z); } //printf(" --> bias factor %g\n", biasFactor); glPopAttrib(); #endif } #endif FX_ENTRY void FX_CALL grDepthBiasLevel( FxI32 level ) { LOG("grDepthBiasLevel(%d)\r\n", level); if (level) { #ifdef ANDROID_EDITION glPolygonOffset(polygonOffsetFactor, polygonOffsetUnits); #else if(w_buffer_mode) glPolygonOffset(1.0f, -(float)level*zscale/255.0f); else glPolygonOffset(0, (float)level*biasFactor); #endif glEnable(GL_POLYGON_OFFSET_FILL); } else { glPolygonOffset(0,0); glDisable(GL_POLYGON_OFFSET_FILL); } } // draw FX_ENTRY void FX_CALL grDrawTriangle( const void *a, const void *b, const void *c ) { LOG("grDrawTriangle()\r\n\t"); if(nvidia_viewport_hack && !render_to_texture) { glViewport(0, viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } reloadTexture(); if(need_to_compile) compile_shader(); if(vertex_buffer_count + 3 > VERTEX_BUFFER_SIZE) { vbo_draw(); } vertex_draw_mode = GL_TRIANGLES; memcpy(&vertex_buffer[vertex_buffer_count],a,VERTEX_SIZE); memcpy(&vertex_buffer[vertex_buffer_count+1],b,VERTEX_SIZE); memcpy(&vertex_buffer[vertex_buffer_count+2],c,VERTEX_SIZE); vertex_buffer_count += 3; } FX_ENTRY void FX_CALL grDrawPoint( const void *pt ) { /* float *x = (float*)pt + xy_off/sizeof(float); float *y = (float*)pt + xy_off/sizeof(float) + 1; float *z = (float*)pt + z_off/sizeof(float); float *q = (float*)pt + q_off/sizeof(float); unsigned char *pargb = (unsigned char*)pt + pargb_off; float *s0 = (float*)pt + st0_off/sizeof(float); float *t0 = (float*)pt + st0_off/sizeof(float) + 1; float *s1 = (float*)pt + st1_off/sizeof(float); float *t1 = (float*)pt + st1_off/sizeof(float) + 1; float *fog = (float*)pt + fog_ext_off/sizeof(float); LOG("grDrawPoint()\r\n"); if(nvidia_viewport_hack && !render_to_texture) { glViewport(0, viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } reloadTexture(); if(need_to_compile) compile_shader(); glBegin(GL_POINTS); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *s0 / *q / (float)tex1_width, ytex(0, *t0 / *q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *s1 / *q / (float)tex0_width, ytex(1, *t1 / *q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*s0 / *q / (float)tex0_width, ytex(0, *t0 / *q / (float)tex0_height)); } if (pargb_en) glColor4f(pargb[2]/255.0f, pargb[1]/255.0f, pargb[0]/255.0f, pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *fog) / 255.0f, 0.0f, 0.0f); } glVertex4f((*x - (float)widtho) / (float)(width/2) / *q, -(*y - (float)heighto) / (float)(height/2) / *q, ZCALC(*z ,*q), 1.0f / *q); glEnd(); */ } FX_ENTRY void FX_CALL grDrawLine( const void *a, const void *b ) { /* float *a_x = (float*)a + xy_off/sizeof(float); float *a_y = (float*)a + xy_off/sizeof(float) + 1; float *a_z = (float*)a + z_off/sizeof(float); float *a_q = (float*)a + q_off/sizeof(float); unsigned char *a_pargb = (unsigned char*)a + pargb_off; float *a_s0 = (float*)a + st0_off/sizeof(float); float *a_t0 = (float*)a + st0_off/sizeof(float) + 1; float *a_s1 = (float*)a + st1_off/sizeof(float); float *a_t1 = (float*)a + st1_off/sizeof(float) + 1; float *a_fog = (float*)a + fog_ext_off/sizeof(float); float *b_x = (float*)b + xy_off/sizeof(float); float *b_y = (float*)b + xy_off/sizeof(float) + 1; float *b_z = (float*)b + z_off/sizeof(float); float *b_q = (float*)b + q_off/sizeof(float); unsigned char *b_pargb = (unsigned char*)b + pargb_off; float *b_s0 = (float*)b + st0_off/sizeof(float); float *b_t0 = (float*)b + st0_off/sizeof(float) + 1; float *b_s1 = (float*)b + st1_off/sizeof(float); float *b_t1 = (float*)b + st1_off/sizeof(float) + 1; float *b_fog = (float*)b + fog_ext_off/sizeof(float); LOG("grDrawLine()\r\n"); if(nvidia_viewport_hack && !render_to_texture) { glViewport(0, viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } reloadTexture(); if(need_to_compile) compile_shader(); glBegin(GL_LINES); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *a_s0 / *a_q / (float)tex1_width, ytex(0, *a_t0 / *a_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *a_s1 / *a_q / (float)tex0_width, ytex(1, *a_t1 / *a_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*a_s0 / *a_q / (float)tex0_width, ytex(0, *a_t0 / *a_q / (float)tex0_height)); } if (pargb_en) glColor4f(a_pargb[2]/255.0f, a_pargb[1]/255.0f, a_pargb[0]/255.0f, a_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *a_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *a_fog) / 255.0f, 0.0f, 0.0f); } glVertex4f((*a_x - (float)widtho) / (float)(width/2) / *a_q, -(*a_y - (float)heighto) / (float)(height/2) / *a_q, ZCALC(*a_z, *a_q), 1.0f / *a_q); if (nbTextureUnits > 2) { if (st0_en) glMultiTexCoord2fARB(GL_TEXTURE1_ARB, *b_s0 / *b_q / (float)tex1_width, ytex(0, *b_t0 / *b_q / (float)tex1_height)); if (st1_en) glMultiTexCoord2fARB(GL_TEXTURE0_ARB, *b_s1 / *b_q / (float)tex0_width, ytex(1, *b_t1 / *b_q / (float)tex0_height)); } else { if (st0_en) glTexCoord2f(*b_s0 / *b_q / (float)tex0_width, ytex(0, *b_t0 / *b_q / (float)tex0_height)); } if (pargb_en) glColor4f(b_pargb[2]/255.0f, b_pargb[1]/255.0f, b_pargb[0]/255.0f, b_pargb[3]/255.0f); if (fog_enabled && fog_coord_support) { if(!fog_ext_en || fog_enabled != 2) glSecondaryColor3f((1.0f / *b_q) / 255.0f, 0.0f, 0.0f); else glSecondaryColor3f((1.0f / *b_fog) / 255.0f, 0.0f, 0.0f); } glVertex4f((*b_x - (float)widtho) / (float)(width/2) / *b_q, -(*b_y - (float)heighto) / (float)(height/2) / *b_q, ZCALC(*b_z, *b_q), 1.0f / *b_q); glEnd(); */ } FX_ENTRY void FX_CALL grDrawVertexArray(FxU32 mode, FxU32 Count, void *pointers2) { void **pointers = (void**)pointers2; LOG("grDrawVertexArray(%d,%d)\r\n", mode, Count); if(nvidia_viewport_hack && !render_to_texture) { glViewport(0, viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } reloadTexture(); if(need_to_compile) compile_shader(); if(mode != GR_TRIANGLE_FAN) { WriteTrace(TraceGlitch, TraceWarning, "grDrawVertexArray : unknown mode : %x", mode); } vbo_enable(); vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers[0]); } FX_ENTRY void FX_CALL grDrawVertexArrayContiguous(FxU32 mode, FxU32 Count, void *pointers, FxU32 stride) { LOG("grDrawVertexArrayContiguous(%d,%d,%d)\r\n", mode, Count, stride); if(nvidia_viewport_hack && !render_to_texture) { glViewport(0, viewport_offset, viewport_width, viewport_height); nvidia_viewport_hack = 0; } if(stride != 156) { LOGINFO("Incompatible stride\n"); } reloadTexture(); if(need_to_compile) compile_shader(); vbo_enable(); switch(mode) { case GR_TRIANGLE_STRIP: vbo_buffer(GL_TRIANGLE_STRIP,0,Count,pointers); break; case GR_TRIANGLE_FAN: vbo_buffer(GL_TRIANGLE_FAN,0,Count,pointers); break; default: WriteTrace(TraceGlitch, TraceWarning, "grDrawVertexArrayContiguous : unknown mode : %x", mode); } }