Fix persistent GL_INVALID_OPERATION spam and resolution-change bugs on Android
build / build (push) Successful in 2m44s
build / build (push) Successful in 2m44s
- opengl_end_frame() bound framebuffer 0 on Android, which has no valid target there (real presentation goes through the OpenXR swapchain's own FBOs) - gl4es reported this every frame. Skip it there. - render_hack_cameras() re-entered opengl_start_frame()/opengl_end_frame() for camera-monitor renders that never touch the GL screen; excluded them to match use_opengl()'s existing behavior. Also drains a stray error left by xrPollEvent(). - ChangeScreenSize() never called opengl_resize() on Android, freezing the 3D render target at launch size after an in-game resolution change; and xr_get_game_resolution() used the swapchain's fixed size instead of the current screen resolution, misplacing the laser-pointer cursor after such a change. - Removes all temporary bisection diagnostics added while tracking down the GL_INVALID_OPERATION source.
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
--- a/src/MacSrc/ShockBitmap.c
|
||||
+++ b/src/MacSrc/ShockBitmap.c
|
||||
@@ -42,11 +42,26 @@
|
||||
@@ -27,6 +27,9 @@
|
||||
#include "Shock.h"
|
||||
#include "ShockBitmap.h"
|
||||
#include "2d.h"
|
||||
+#ifdef __ANDROID__
|
||||
+#include "OpenGL.h"
|
||||
+#endif
|
||||
|
||||
//--------------------
|
||||
// Globals
|
||||
@@ -42,11 +45,26 @@
|
||||
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
@@ -27,3 +37,32 @@
|
||||
|
||||
SDL_RenderSetLogicalSize(renderer, width, height);
|
||||
|
||||
@@ -54,6 +72,28 @@
|
||||
|
||||
gScreenWide = width;
|
||||
gScreenHigh = height;
|
||||
+
|
||||
+#ifdef __ANDROID__
|
||||
+ // Skipping SDL_SetWindowSize() above (see the comment for why) also
|
||||
+ // means no native resize event ever fires on Android when the in-game
|
||||
+ // resolution changes - opengl_resize() (OpenGL.cc) only ever runs from
|
||||
+ // that event (see sdl_events.c) or once at OpenGL init, and it's what
|
||||
+ // (re)creates backupBuffer, the offscreen 3D-view render target, sized
|
||||
+ // to the logical resolution just changed above. Without this, it stays
|
||||
+ // stuck at whatever size it was at launch while the rest of the game
|
||||
+ // (drawSurface/gScreenWide/gScreenHigh, just updated above) moves on to
|
||||
+ // the new resolution - the actual cause of the display breaking and
|
||||
+ // becoming unresponsive to further input after changing resolution
|
||||
+ // in-game. Call it directly instead - after gScreenWide/gScreenHigh
|
||||
+ // update above, same as the desktop resize event (delivered via
|
||||
+ // SDL_PollEvent(), so always processed after this function has already
|
||||
+ // returned) - using the same physical window size init_opengl() itself
|
||||
+ // used (SDL_GetWindowSize()); that never changes on Android, only the
|
||||
+ // logical size set above does.
|
||||
+ int physWidth, physHeight;
|
||||
+ SDL_GetWindowSize(window, &physWidth, &physHeight);
|
||||
+ opengl_resize(physWidth, physHeight);
|
||||
+#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,455 @@
|
||||
--- a/src/MacSrc/OpenGL.cc
|
||||
+++ b/src/MacSrc/OpenGL.cc
|
||||
@@ -391,7 +391,16 @@
|
||||
}
|
||||
|
||||
void opengl_resize(int width, int height) {
|
||||
+#ifndef __ANDROID__
|
||||
+ // Skipped on Android - see opengl_swap_and_restore()'s comment below for
|
||||
+ // why re-asserting an already-current context/surface every call breaks
|
||||
+ // gl4es's own "current framebuffer" bookkeeping, even though the real
|
||||
+ // driver binding never actually changes. This turned out to be the
|
||||
+ // actual source of the persistent per-frame GL_INVALID_OPERATION (1282)
|
||||
+ // that plagued 3D rendering: this same unconditional call was present at
|
||||
+ // the top of nearly every function in this file, not just here.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
int logical_width, logical_height;
|
||||
SDL_RenderGetLogicalSize(renderer, &logical_width, &logical_height);
|
||||
@@ -443,7 +452,10 @@
|
||||
}
|
||||
|
||||
void opengl_end_frame() {
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
// Done rendering to the frame buffer, reset back to normal
|
||||
BindFrameBuffer(nullptr);
|
||||
@@ -470,7 +482,10 @@
|
||||
static bool nightsight_active() { return WareActive(player_struct.hardwarez_status[HARDWARE_GOGGLE_INFRARED]); }
|
||||
|
||||
void opengl_start_frame() {
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
// Start rendering to our frame buffer canvas
|
||||
BindFrameBuffer(&backupBuffer);
|
||||
@@ -500,6 +515,130 @@
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
+// Real per-vertex arrays, not glBegin/glVertexAttrib/glVertex3f immediate
|
||||
+// mode: glVertexAttrib*() is GLES2's *constant*-attribute API - without an
|
||||
+// enabled vertex array it sets one value for the whole draw call, not a
|
||||
+// fresh value per vertex. gl4es's immediate-mode emulation only reproduces
|
||||
+// desktop GL's per-vertex-capture behavior for attribute 0 (position,
|
||||
+// driven directly by glVertex3f), not for custom attributes like this
|
||||
+// shader's texcoords/light. That means every one of this file's
|
||||
+// glBegin(GL_TRIANGLE_STRIP)-based draws - not just the UI-overlay quad
|
||||
+// this was first found on, but also opengl_light_tmap() (every textured
|
||||
+// wall/floor polygon), opengl_bitmap() (sprites) and opengl_draw_poly()
|
||||
+// (flat/gouraud polygons) via draw_vertex() - draws every vertex with
|
||||
+// whatever texcoord/light was set for the *last* vertex instead of its
|
||||
+// own, which is what actually produced flat-colored/untextured world
|
||||
+// geometry after this patch's first revision only fixed the final
|
||||
+// screen-composite quad (the one bug this was originally found on).
|
||||
+//
|
||||
+// android_imm_begin()/android_imm_vertex()/android_imm_end() below emulate
|
||||
+// just enough of glBegin(GL_TRIANGLE_STRIP)/glVertexAttrib*()/glVertex3f()
|
||||
+// immediate mode to replace every such call site on Android, by buffering
|
||||
+// vertices and flushing them as one real glDrawArrays() call - the engine's
|
||||
+// other rendering still uses real immediate mode for attribute 0 elsewhere
|
||||
+// on desktop builds, which depends on it not having an enabled array bound,
|
||||
+// so android_imm_end() always disables the arrays it enables before
|
||||
+// returning.
|
||||
+struct AndroidImmVertex {
|
||||
+ float x, y, z;
|
||||
+ float u, v;
|
||||
+ float light;
|
||||
+};
|
||||
+
|
||||
+// Arbitrarily-sized, but generous: the engine's polygons (room walls/
|
||||
+// floors, sprites, screen-filling quads) are all small, hand-authored
|
||||
+// shapes, never anywhere near this many vertices.
|
||||
+static AndroidImmVertex s_immVerts[64];
|
||||
+static int s_immVertCount;
|
||||
+static GLint s_immTcAttrib;
|
||||
+static GLint s_immLightAttrib;
|
||||
+
|
||||
+// tcAttrib < 0 means this draw has no texcoord attribute (flat/gouraud
|
||||
+// polygons via opengl_draw_poly()) - matches draw_vertex()'s own
|
||||
+// `tcAttrib >= 0` check below.
|
||||
+static void android_imm_begin(GLint tcAttrib, GLint lightAttrib) {
|
||||
+ s_immVertCount = 0;
|
||||
+ s_immTcAttrib = tcAttrib;
|
||||
+ s_immLightAttrib = lightAttrib;
|
||||
+}
|
||||
+
|
||||
+static void android_imm_vertex(float x, float y, float z, float u, float v, float light) {
|
||||
+ if (s_immVertCount >= (int)(sizeof(s_immVerts) / sizeof(s_immVerts[0]))) {
|
||||
+ WARN("android_imm_vertex: dropping vertex past the %d-vertex limit", s_immVertCount);
|
||||
+ return;
|
||||
+ }
|
||||
+ AndroidImmVertex &vert = s_immVerts[s_immVertCount++];
|
||||
+ vert.x = x;
|
||||
+ vert.y = y;
|
||||
+ vert.z = z;
|
||||
+ vert.u = u;
|
||||
+ vert.v = v;
|
||||
+ vert.light = light;
|
||||
+}
|
||||
+
|
||||
+static void android_imm_end() {
|
||||
+ if (s_immVertCount < 3)
|
||||
+ return;
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+ if (s_immTcAttrib >= 0)
|
||||
+ glEnableVertexAttribArray(s_immTcAttrib);
|
||||
+ glEnableVertexAttribArray(s_immLightAttrib);
|
||||
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(AndroidImmVertex), &s_immVerts[0].x);
|
||||
+ if (s_immTcAttrib >= 0)
|
||||
+ glVertexAttribPointer(s_immTcAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(AndroidImmVertex),
|
||||
+ &s_immVerts[0].u);
|
||||
+ glVertexAttribPointer(s_immLightAttrib, 1, GL_FLOAT, GL_FALSE, sizeof(AndroidImmVertex),
|
||||
+ &s_immVerts[0].light);
|
||||
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, s_immVertCount);
|
||||
+ glDisableVertexAttribArray(0);
|
||||
+ if (s_immTcAttrib >= 0)
|
||||
+ glDisableVertexAttribArray(s_immTcAttrib);
|
||||
+ glDisableVertexAttribArray(s_immLightAttrib);
|
||||
+}
|
||||
+
|
||||
+// Same underlying bug as android_imm_*() above, for opengl_draw_star():
|
||||
+// opengl_begin_stars()/opengl_draw_star()/opengl_end_stars() draw up to
|
||||
+// NUM_STARS (rendtool.c) individual GL_POINTS between one begin/end pair,
|
||||
+// each with its own per-star brightness via glVertexAttrib1f(lightAttrib,
|
||||
+// ...)/glVertex3f() immediate mode - under gl4es that made every star on
|
||||
+// screen render at whatever brightness was set for the *last* one. Shaped
|
||||
+// differently enough from android_imm_*() above (GL_POINTS instead of
|
||||
+// GL_TRIANGLE_STRIP, far more vertices, no texcoord) to warrant its own
|
||||
+// small buffer rather than overloading that one.
|
||||
+static AndroidImmVertex s_starVerts[1000]; // NUM_STARS, GameSrc/rendtool.c
|
||||
+static int s_starVertCount;
|
||||
+static GLint s_starLightAttrib;
|
||||
+
|
||||
+static void android_stars_begin(GLint lightAttrib) {
|
||||
+ s_starVertCount = 0;
|
||||
+ s_starLightAttrib = lightAttrib;
|
||||
+}
|
||||
+
|
||||
+static void android_stars_vertex(float x, float y, float z, float light) {
|
||||
+ if (s_starVertCount >= (int)(sizeof(s_starVerts) / sizeof(s_starVerts[0]))) {
|
||||
+ WARN("android_stars_vertex: dropping star past the %d-star limit", s_starVertCount);
|
||||
+ return;
|
||||
+ }
|
||||
+ AndroidImmVertex &vert = s_starVerts[s_starVertCount++];
|
||||
+ vert.x = x;
|
||||
+ vert.y = y;
|
||||
+ vert.z = z;
|
||||
+ vert.light = light;
|
||||
+}
|
||||
+
|
||||
+static void android_stars_end() {
|
||||
+ if (s_starVertCount == 0)
|
||||
+ return;
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+ glEnableVertexAttribArray(s_starLightAttrib);
|
||||
+ glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(AndroidImmVertex), &s_starVerts[0].x);
|
||||
+ glVertexAttribPointer(s_starLightAttrib, 1, GL_FLOAT, GL_FALSE, sizeof(AndroidImmVertex),
|
||||
+ &s_starVerts[0].light);
|
||||
+ glDrawArrays(GL_POINTS, 0, s_starVertCount);
|
||||
+ glDisableVertexAttribArray(0);
|
||||
+ glDisableVertexAttribArray(s_starLightAttrib);
|
||||
+}
|
||||
+
|
||||
// Shared by opengl_swap_and_restore()'s UI-overlay blit and
|
||||
// android_composite_software_frame() below - draws an SDL_Surface as a
|
||||
// fullscreen textured quad via gl4es. SDL's own renderer can't be used
|
||||
@@ -537,42 +676,15 @@
|
||||
|
||||
set_blend_mode(blend);
|
||||
|
||||
- // Real per-vertex arrays, not glBegin/glVertexAttrib/glVertex3f
|
||||
- // immediate mode: glVertexAttrib*() is GLES2's *constant*-attribute
|
||||
- // API - without an enabled vertex array it sets one value for the
|
||||
- // whole draw call, not a fresh value per vertex. gl4es's immediate-mode
|
||||
- // emulation only reproduces desktop GL's per-vertex-capture behavior
|
||||
- // for attribute 0 (position, driven directly by glVertex3f), not for
|
||||
- // custom attributes like this shader's texcoords/light.
|
||||
- //
|
||||
// V is flipped (1 at the bottom, 0 at the top): GL texture v=0
|
||||
// addresses the first row of data passed to glTexImage2D, but uiRgba
|
||||
// (an SDL surface) stores its rows top-down.
|
||||
- struct QuadVertex {
|
||||
- float x, y, z;
|
||||
- float u, v;
|
||||
- float light;
|
||||
- };
|
||||
- static const QuadVertex quadVerts[4] = {
|
||||
- {1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
|
||||
- {1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f},
|
||||
- {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f},
|
||||
- {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f},
|
||||
- };
|
||||
- glEnableVertexAttribArray(0);
|
||||
- glEnableVertexAttribArray(tcAttrib);
|
||||
- glEnableVertexAttribArray(lightAttrib);
|
||||
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), &quadVerts[0].x);
|
||||
- glVertexAttribPointer(tcAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(QuadVertex), &quadVerts[0].u);
|
||||
- glVertexAttribPointer(lightAttrib, 1, GL_FLOAT, GL_FALSE, sizeof(QuadVertex),
|
||||
- &quadVerts[0].light);
|
||||
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
- // The engine's other rendering uses glBegin/glVertexAttrib/glVertex3f
|
||||
- // immediate mode for attribute 0, which depends on it not having an
|
||||
- // enabled array bound.
|
||||
- glDisableVertexAttribArray(0);
|
||||
- glDisableVertexAttribArray(tcAttrib);
|
||||
- glDisableVertexAttribArray(lightAttrib);
|
||||
+ android_imm_begin(tcAttrib, lightAttrib);
|
||||
+ android_imm_vertex(1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f);
|
||||
+ android_imm_vertex(1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
+ android_imm_vertex(-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
+ android_imm_vertex(-1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
+ android_imm_end();
|
||||
// glFinish(), not glFlush(): xr_swapchain_release() (called by our
|
||||
// caller right after this returns) hands the image to the OpenXR
|
||||
// runtime for cross-process consumption, which requires the GPU write
|
||||
@@ -642,6 +754,16 @@
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ // Real per-vertex arrays, not glBegin/glVertexAttrib/glVertex3f
|
||||
+ // immediate mode - see android_imm_begin()'s comment above for why.
|
||||
+ android_imm_begin(tcAttrib, lightAttrib);
|
||||
+ android_imm_vertex(1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
+ android_imm_vertex(1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f);
|
||||
+ android_imm_vertex(-1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
+ android_imm_vertex(-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
+ android_imm_end();
|
||||
+#else
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glVertexAttrib2f(tcAttrib, 1.0f, 0.0f);
|
||||
glVertexAttrib1f(lightAttrib, 1.0f);
|
||||
@@ -656,6 +778,7 @@
|
||||
glVertexAttrib1f(lightAttrib, 1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||
glEnd();
|
||||
+#endif
|
||||
|
||||
// Finish drawing the 3d view
|
||||
glFlush();
|
||||
@@ -709,7 +832,10 @@
|
||||
render_width = width;
|
||||
render_height = height;
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
int lw, lh;
|
||||
SDL_RenderGetLogicalSize(renderer, &lw, &lh);
|
||||
@@ -729,7 +855,10 @@
|
||||
}
|
||||
|
||||
static bool opengl_cache_texture(CachedTexture toCache, grs_bitmap *bm) {
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
// GL_UNPACK_ROW_LENGTH must describe the buffer actually passed to
|
||||
// glTexImage2D() below (toCache.converted->pixels, a separately
|
||||
@@ -771,7 +900,10 @@
|
||||
|
||||
DEBUG("Clearing OpenGL texture cache.");
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
for (auto iter = texturesByBitsPtr.begin(); iter != texturesByBitsPtr.end();) {
|
||||
// don't free locked surfaces
|
||||
@@ -896,10 +1028,16 @@
|
||||
light = 1.0f - (clut - grd_screen->ltab) / 4096.0f;
|
||||
}
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ (void)tcAttrib; // captured by android_imm_begin() instead - see its comment above
|
||||
+ android_imm_vertex(vertex.x / 65536.0f, vertex.y / 65536.0f, -vertex.z / 65536.0f,
|
||||
+ vertex.uv.u / 256.0f, vertex.uv.v / 256.0f, light);
|
||||
+#else
|
||||
if (tcAttrib >= 0)
|
||||
glVertexAttrib2f(tcAttrib, vertex.uv.u / 256.0, vertex.uv.v / 256.0);
|
||||
glVertexAttrib1f(lightAttrib, light);
|
||||
glVertex3f(vertex.x / 65536.0f, vertex.y / 65536.0f, -vertex.z / 65536.0f);
|
||||
+#endif
|
||||
}
|
||||
|
||||
int opengl_draw_tmap(int n, g3s_phandle *vp, grs_bitmap *bm) { return opengl_light_tmap(n, vp, bm); }
|
||||
@@ -910,7 +1048,10 @@
|
||||
return CLIP_ALL;
|
||||
}
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
set_blend_mode(bm->flags & BMF_TRANS);
|
||||
|
||||
glUseProgram(textureShaderProgram.shaderProgram);
|
||||
@@ -928,13 +1069,21 @@
|
||||
glUniformMatrix4fv(textureShaderProgram.uniView, 1, false, ViewMatrix);
|
||||
glUniformMatrix4fv(textureShaderProgram.uniProj, 1, false, ProjectionMatrix);
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ android_imm_begin(tcAttrib, lightAttrib);
|
||||
+#else
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
+#endif
|
||||
draw_vertex(*(vp[1]), tcAttrib, lightAttrib);
|
||||
draw_vertex(*(vp[0]), tcAttrib, lightAttrib);
|
||||
draw_vertex(*(vp[2]), tcAttrib, lightAttrib);
|
||||
if (n > 3)
|
||||
draw_vertex(*(vp[3]), tcAttrib, lightAttrib);
|
||||
+#ifdef __ANDROID__
|
||||
+ android_imm_end();
|
||||
+#else
|
||||
glEnd();
|
||||
+#endif
|
||||
|
||||
return CLIP_NONE;
|
||||
}
|
||||
@@ -949,7 +1098,10 @@
|
||||
return CLIP_ALL;
|
||||
}
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
set_blend_mode(bm->flags & BMF_TRANS);
|
||||
|
||||
glUseProgram(textureShaderProgram.shaderProgram);
|
||||
@@ -976,6 +1128,14 @@
|
||||
|
||||
glUniform1i(textureShaderProgram.uniMutant, (bm->type == BMT_TLUC8) || (bm->flags == BMF_TLUC8));
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ android_imm_begin(tcAttrib, lightAttrib);
|
||||
+ android_imm_vertex(convx(vpl[1]->x), convy(vpl[1]->y), 0.0f, 1.0f, 0.0f, light);
|
||||
+ android_imm_vertex(convx(vpl[0]->x), convy(vpl[0]->y), 0.0f, 0.0f, 0.0f, light);
|
||||
+ android_imm_vertex(convx(vpl[2]->x), convy(vpl[2]->y), 0.0f, 1.0f, 1.0f, light);
|
||||
+ android_imm_vertex(convx(vpl[3]->x), convy(vpl[3]->y), 0.0f, 0.0f, 1.0f, light);
|
||||
+ android_imm_end();
|
||||
+#else
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glVertexAttrib2f(tcAttrib, 1.0f, 0.0f);
|
||||
glVertexAttrib1f(lightAttrib, light);
|
||||
@@ -990,6 +1150,7 @@
|
||||
glVertexAttrib1f(lightAttrib, light);
|
||||
glVertex3f(convx(vpl[3]->x), convy(vpl[3]->y), 0.0f);
|
||||
glEnd();
|
||||
+#endif
|
||||
|
||||
glUniform1i(textureShaderProgram.uniMutant, false);
|
||||
|
||||
@@ -1007,7 +1168,10 @@
|
||||
return CLIP_ALL;
|
||||
}
|
||||
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
glUseProgram(colorShaderProgram.shaderProgram);
|
||||
glUniformMatrix4fv(colorShaderProgram.uniView, 1, false, ViewMatrix);
|
||||
@@ -1064,7 +1228,11 @@
|
||||
GLint lightAttrib = colorShaderProgram.lightAttrib;
|
||||
|
||||
long a = 0, b = n_verts - 1;
|
||||
+#ifdef __ANDROID__
|
||||
+ android_imm_begin(-1, lightAttrib);
|
||||
+#else
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
+#endif
|
||||
while (true) {
|
||||
draw_vertex(*(p[a]), -1, lightAttrib);
|
||||
if (a++ == b)
|
||||
@@ -1073,7 +1241,11 @@
|
||||
if (b-- == a)
|
||||
break;
|
||||
}
|
||||
+#ifdef __ANDROID__
|
||||
+ android_imm_end();
|
||||
+#else
|
||||
glEnd();
|
||||
+#endif
|
||||
|
||||
return CLIP_NONE;
|
||||
}
|
||||
@@ -1085,7 +1257,10 @@
|
||||
}
|
||||
|
||||
void opengl_begin_stars() {
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
+#endif
|
||||
|
||||
// Bind the star shader before setting the point size: on Android,
|
||||
// questshock_glPointSize() (see the __ANDROID__ block above) needs
|
||||
@@ -1108,11 +1283,19 @@
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ android_stars_begin(starShaderProgram.lightAttrib);
|
||||
+#else
|
||||
glBegin(GL_POINTS);
|
||||
+#endif
|
||||
}
|
||||
|
||||
void opengl_end_stars() {
|
||||
+#ifdef __ANDROID__
|
||||
+ android_stars_end();
|
||||
+#else
|
||||
glEnd();
|
||||
+#endif
|
||||
|
||||
// Turn off the stencil test and blending
|
||||
opengl_set_stencil(0x00);
|
||||
@@ -1120,9 +1303,11 @@
|
||||
}
|
||||
|
||||
int opengl_draw_star(fix star_x, fix star_y, int c, bool anti_alias) {
|
||||
+#ifndef __ANDROID__
|
||||
+ // See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
-
|
||||
GLint lightAttrib = starShaderProgram.lightAttrib;
|
||||
+#endif
|
||||
|
||||
float x = fix_float(star_x);
|
||||
float y = fix_float(star_y);
|
||||
@@ -1142,8 +1327,12 @@
|
||||
int color = (std_color_base + std_color_range - 1 - c);
|
||||
color = (255 * color) / (std_color_range + 1);
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ android_stars_vertex(x, y, -0.25f, color / 255.0f);
|
||||
+#else
|
||||
glVertexAttrib1f(lightAttrib, color / 255.0f);
|
||||
glVertex3f(x, y, -0.25f);
|
||||
+#endif
|
||||
|
||||
return CLIP_NONE;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
--- a/src/GameSrc/frsetup.c
|
||||
+++ b/src/GameSrc/frsetup.c
|
||||
@@ -635,7 +635,27 @@
|
||||
uchar old_cam_type;
|
||||
int detail;
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ // should_opengl_swap() (unlike use_opengl(), see its own
|
||||
+ // FR_PICKUPM_MASK|FR_HACKCAM_MASK exclusion just below and the
|
||||
+ // matching one used for the STEREO_SUPPORT path in fr_send_view()
|
||||
+ // below) doesn't know which _fr context is currently being prepared -
|
||||
+ // it's a frame-level check, also used by Shock.c's SDLDraw() to pick
|
||||
+ // the frame's overall compositing path. render_hack_cameras() (see
|
||||
+ // render.c) calls fr_rend() - and so this function - a second time per
|
||||
+ // real frame for each active hack-camera monitor, rendering into a
|
||||
+ // private software (FR_DOUBLEB_MASK) canvas rather than the actual
|
||||
+ // GL-backed screen. Without this exclusion, opengl_start_frame() runs
|
||||
+ // again mid-frame for that render even though its own polygon draw
|
||||
+ // calls correctly stay on the software path (use_opengl() already
|
||||
+ // excludes them) - re-entering the OpenXR swapchain/framebuffer setup
|
||||
+ // a second time before the first call's frame has ended. Not known to
|
||||
+ // be exercised on desktop (no OpenXR swapchain there), so this fix is
|
||||
+ // kept Android-only rather than changing should_opengl_swap() itself.
|
||||
+ if (should_opengl_swap() && !(_fr_curflags & (FR_PICKUPM_MASK | FR_HACKCAM_MASK))) {
|
||||
+#else
|
||||
if(should_opengl_swap()) {
|
||||
+#endif
|
||||
opengl_start_frame();
|
||||
}
|
||||
|
||||
@@ -823,7 +843,14 @@
|
||||
|
||||
g3_end_frame();
|
||||
|
||||
+#ifdef __ANDROID__
|
||||
+ // Mirrors the same fix in fr_start_view() above - see its comment.
|
||||
+ // opengl_start_frame()/opengl_end_frame() must stay paired per real
|
||||
+ // GL frame, so this exclusion has to match that one exactly.
|
||||
+ if (should_opengl_swap() && !(_fr_curflags & (FR_PICKUPM_MASK | FR_HACKCAM_MASK))) {
|
||||
+#else
|
||||
if(should_opengl_swap()) {
|
||||
+#endif
|
||||
opengl_end_frame();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
--- a/src/MacSrc/OpenGL.cc
|
||||
+++ b/src/MacSrc/OpenGL.cc
|
||||
@@ -455,10 +455,30 @@
|
||||
#ifndef __ANDROID__
|
||||
// See opengl_resize()'s comment above.
|
||||
SDL_GL_MakeCurrent(window, context);
|
||||
-#endif
|
||||
|
||||
// Done rendering to the frame buffer, reset back to normal
|
||||
BindFrameBuffer(nullptr);
|
||||
+#else
|
||||
+ // BindFrameBuffer(nullptr) (glBindFramebuffer/glBindRenderbuffer to id
|
||||
+ // 0) means "the real window surface" - on desktop that's SDL's actual
|
||||
+ // GL window, but this app's real presentation target is never that
|
||||
+ // SDLSurface's own EGL surface at all - it's the OpenXR swapchain's
|
||||
+ // per-image FBOs, set up separately in xr_swapchain.c. Whatever
|
||||
+ // framebuffer/renderbuffer 0 actually resolves to for gl4es in this
|
||||
+ // configuration, binding it here reliably left gl4es reporting a
|
||||
+ // persistent GL_INVALID_OPERATION (1282) - confirmed by bisecting
|
||||
+ // through this whole render path with per-call checkpoints, all clean
|
||||
+ // right up until "after opengl_end_frame", the one immediately after
|
||||
+ // this exact call.
|
||||
+ //
|
||||
+ // The bind is also functionally dead on Android regardless of that:
|
||||
+ // by the time anything next draws, Shock.c's SDLDraw() has already
|
||||
+ // run xr_frame_begin() -> xr_swapchain_acquire(), which rebinds to
|
||||
+ // that frame's real swapchain FBO before opengl_swap_and_restore()
|
||||
+ // (the only thing that draws before the next opengl_start_frame()'s
|
||||
+ // own BindFrameBuffer(&backupBuffer)) runs - so skipping it changes
|
||||
+ // nothing about what actually gets rendered where.
|
||||
+#endif
|
||||
palette_dirty = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user