X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgl%2Frender.c;h=b5da71f4c4949fe01456cc8fb2677e08866919f1;hb=b7c39e0d9229a7616c63cf545cdd9576b9bf3e2c;hp=e9dc5b5addb443537778fc50ed596e4a0f05244b;hpb=c5be09436899f403e3f39c051399b160c8d2f019;p=flatwaifu.git diff --git a/src/gl/render.c b/src/gl/render.c index e9dc5b5..b5da71f 100644 --- a/src/gl/render.c +++ b/src/gl/render.c @@ -21,7 +21,11 @@ #include "view.h" #include "switch.h" // sw_secrets -#include +#ifdef __APPLE__ +# include +#else +# include +#endif #include // malloc free abs #include // assert #include @@ -53,6 +57,7 @@ typedef struct rgba { typedef struct node { struct cache *base; struct node *left, *right; + struct node *up; int l, t, r, b; int leaf; } node; @@ -78,6 +83,7 @@ static int fullscreen; static SDL_Surface *surf; static rgb playpal[256]; static byte bright[256]; +static GLuint lastTexture; static cache *root; /* Game */ @@ -176,12 +182,14 @@ static node *R_node_alloc (node *p, int w, int h) { p->right = malloc(sizeof(node)); if (pw - w > ph - h) { *p->left = (node) { + .up = p, .l = p->l, .t = p->t, .r = p->l + w - 1, .b = p->b }; *p->right = (node) { + .up = p, .l = p->l + w, .t = p->t, .r = p->r, @@ -189,12 +197,14 @@ static node *R_node_alloc (node *p, int w, int h) { }; } else { *p->left = (node) { + .up = p, .l = p->l, .t = p->t, .r = p->r, .b = p->t + h - 1 }; *p->right = (node) { + .up = p, .l = p->l, .t = p->t + h, .r = p->r, @@ -206,49 +216,105 @@ static node *R_node_alloc (node *p, int w, int h) { } } +static int R_node_have_leaf (node *n) { + return n && (n->leaf || R_node_have_leaf(n->left) || R_node_have_leaf(n->right)); +} + +static void R_node_free_recursive (node *n) { + if (n) { + R_node_free_recursive(n->left); + R_node_free_recursive(n->right); + free(n); + } +} + +static void R_node_free (node *n) { + if (n) { + //logo("free node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b); + assert(n->leaf); + assert(n->left == NULL); + assert(n->right == NULL); + n->leaf = 0; + n->base = NULL; + node *p = n->up; + while (p != NULL) { + assert(p->leaf == 0); + assert(p->left); + assert(p->right); + if (R_node_have_leaf(p) == 0) { + R_node_free_recursive(p->left); + p->left = NULL; + R_node_free_recursive(p->right); + p->right = NULL; + p = p->up; + } else { + p = NULL; + } + } + } +} + +static void R_gl_bind_texture (GLuint id) { + if (id != lastTexture) { + glBindTexture(GL_TEXTURE_2D, id); + } +} + static cache *R_cache_new (void) { GLuint id = 0; GLint size = 0; cache *c = NULL; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size); - size /= 2; // TODO remove hack or detect ibook bug + size = size < 512 ? size : 512; // more can be buggy on older hardware if (size) { glGenTextures(1, &id); if (id) { - glBindTexture(GL_TEXTURE_2D, id); + R_gl_bind_texture(id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - int ok = glGetError() == GL_NO_ERROR; - glBindTexture(GL_TEXTURE_2D, 0); - if (ok) { - c = malloc(sizeof(cache)); - if (c != NULL) { - *c = (cache) { - .id = id, - .root.r = size - 1, - .root.b = size - 1 - }; - } - } - if (c == NULL) { + c = malloc(sizeof(cache)); + if (c != NULL) { + *c = (cache) { + .id = id, + .root.r = size - 1, + .root.b = size - 1 + }; + } else { glDeleteTextures(1, &id); } } } - logo("new cache %p\n", c); + //logo("new cache %p\n", c); return c; } +static void R_cache_free (cache *root, int freetexture) { + cache *next; + cache *c = root; + while (c != NULL) { + next = c->next; + R_node_free_recursive(c->root.left); + R_node_free_recursive(c->root.right); + if (freetexture && c->id != 0) { + glDeleteTextures(1, &c->id); + } + free(c); + c = next; + } +} + static node *R_cache_alloc (cache *root, int w, int h) { assert(root); assert(w > 0 && h > 0); node *n = NULL; cache *p = NULL; cache *c = root; + // TODO return null if required size greater than maximum while (c && !n) { n = R_node_alloc(&c->root, w, h); if (n) { + assert(n->leaf); n->base = c; } p = c; @@ -260,25 +326,30 @@ static node *R_cache_alloc (cache *root, int w, int h) { p->next = c; n = R_node_alloc(&c->root, w, h); if (n) { + assert(n->leaf); n->base = c; } } } + if (n) { + //logo("new node %p {%i:%i:%i:%i}\n", n, n->l, n->t, n->r, n->b); + } else { + logo("new node failed\n"); + } return n; } static void R_cache_update (node *n, const void *data, int w, int h) { assert(n); + assert(n->leaf); assert(n->base); assert(data); int nw = n->r - n->l + 1; int nh = n->b - n->t + 1; assert(w == nw); assert(h == nh); - glBindTexture(GL_TEXTURE_2D, n->base->id); + R_gl_bind_texture(n->base->id); glTexSubImage2D(GL_TEXTURE_2D, 0, n->l, n->t, nw, nh, GL_RGBA, GL_UNSIGNED_BYTE, data); - assert(glGetError() == GL_NO_ERROR); - glBindTexture(GL_TEXTURE_2D, 0); } /* Generic helpers */ @@ -421,7 +492,7 @@ static image R_gl_create_image (const rgba *buf, int w, int h) { } static image R_gl_get_special_image (int id, rgba *(*fn)(vgaimg*)) { - image img = (image) { .res = -1 }; + image img; vgaimg *v = R_getvga(id); if (v != NULL) { rgba *buf = (*fn)(v); @@ -431,6 +502,10 @@ static image R_gl_get_special_image (int id, rgba *(*fn)(vgaimg*)) { img.res = id; M_unlock(v); free(buf); + } else { + img = (image) { + .res = id + }; } return img; } @@ -449,9 +524,10 @@ static image R_gl_get_special_spr (const char n[4], int s, int d, rgba *(*fn)(vg static void R_gl_free_image (image *img) { if (img->n != NULL && img->res >= 0) { - // TODO delete node + R_node_free(img->n); } img->n = NULL; + img->res = -1; } static void R_gl_draw_quad (int x, int y, int w, int h) { @@ -471,7 +547,7 @@ static void R_gl_draw_textured (image *img, int x, int y, int w, int h, int flip GLfloat bx = (flip ? img->n->r + 1 : img->n->l) / nh; GLfloat ay = (img->n->t) / nw; GLfloat by = (img->n->b + 1) / nh; - glBindTexture(GL_TEXTURE_2D, img->n->base->id); + R_gl_bind_texture(img->n->base->id); glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f(ax, ay); glVertex2i(x + w, y); @@ -479,12 +555,11 @@ static void R_gl_draw_textured (image *img, int x, int y, int w, int h, int flip glTexCoord2f(bx, by); glVertex2i(x, y + h); glTexCoord2f(ax, by); glVertex2i(x + w, y + h); glEnd(); - glDisable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); } else { glColor3ub(255, 0, 0); glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); R_gl_draw_quad(x, y, w, h); } } @@ -503,16 +578,12 @@ static void R_gl_draw_image_color (image *img, int x, int y, int flip) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_gl_draw_textured(img, xx, y - img->y, img->w, img->h, flip); - glDisable(GL_BLEND); } /* draw sprite with offset */ static void R_gl_draw_image (image *img, int x, int y, int flip) { - int xx = flip ? x - img->w + img->x : x - img->x; - glEnable(GL_BLEND); glColor3ub(255, 255, 255); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - R_gl_draw_textured(img, xx, y - img->y, img->w, img->h, flip); + R_gl_draw_image_color(img, x, y, flip); } static void R_gl_set_color (byte c) { @@ -765,6 +836,7 @@ static void R_draw_fld (byte *fld, int minx, int miny, int maxx, int maxy, int f } glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + glDisable(GL_TEXTURE_2D); R_gl_draw_quad(i * CELW, j * CELW, CELW, CELH); } } else { @@ -777,6 +849,9 @@ static void R_draw_fld (byte *fld, int minx, int miny, int maxx, int maxy, int f static void R_draw_dots (void) { int i; + glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); glBegin(GL_POINTS); for (i = 0; i < MAXDOT; i++) { if (dot[i].t != 0) { @@ -1082,6 +1157,9 @@ static void R_draw_effects (void) { R_gl_draw_image(&fx_spr[s], fx[i].x, fx[i].y, fx_sprd[s]); break; case BUBL: + glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); glBegin(GL_POINTS); R_gl_set_color(0xC0 + fx[i].s); glVertex2i(fx[i].x >> 8, (fx[i].y >> 8) + 1); @@ -1117,6 +1195,8 @@ static void R_draw_view (int x, int y, int w, int h, int camx, int camy) { } } else { glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); R_gl_set_color(DEFAULT_SKY_COLOR); R_gl_draw_quad(0, 0, w, h); } @@ -1142,6 +1222,7 @@ static void R_draw_view (int x, int y, int w, int h, int camx, int camy) { glColor4ub(255, 255, 255, 255); glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); + glDisable(GL_TEXTURE_2D); R_gl_draw_quad(0, 0, w, h); } glPopMatrix(); @@ -1161,22 +1242,25 @@ static void R_draw_player_view (player_t *p, int x, int y, int w, int h) { if (p->invl) { if (get_pu_st(p->invl)) { glEnable(GL_BLEND); - glColor4ub(191, 191, 191, 255); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glDisable(GL_TEXTURE_2D); + glColor4ub(191, 191, 191, 255); R_gl_draw_quad(0, 0, cw, h); } } else { if (p->suit && get_pu_st(p->suit)) { glEnable(GL_BLEND); - glColor4ub(0, 255, 0, 192); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + glColor4ub(0, 255, 0, 192); R_gl_draw_quad(0, 0, cw, h); } int f = min(max(p->pain * 3, 0), 255); if (f > 0) { glEnable(GL_BLEND); - glColor4ub(255, 0, 0, f); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + glColor4ub(255, 0, 0, f); R_gl_draw_quad(0, 0, cw, h); } } @@ -1192,6 +1276,8 @@ static void R_draw_player_view (player_t *p, int x, int y, int w, int h) { if (p->air < PL_AIR) { int a = min(max(p->air, 0), MAXAIR) * 100 / MAXAIR; glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); R_gl_set_color(0xC8); R_gl_draw_quad(10, 49, a, 2); } @@ -1312,7 +1398,7 @@ static void W_act (void) { void R_draw (void) { W_act(); glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_SCISSOR_TEST); R_gl_setmatrix(); switch (g_st) { @@ -1594,7 +1680,7 @@ void R_init (void) { } void R_done (void) { - // do nothing + R_cache_free(root, 1); } void R_setgamma (int g) { @@ -1628,10 +1714,10 @@ void R_get_name (int n, char s[8]) { static short getani (char n[8]) { short i = 0; - while (i < ANIT && strncasecmp(n, anm[i][0], 8) != 0) { + while (i < ANIT - 1 && strncasecmp(n, anm[i][0], 8) != 0) { i++; } - return i < ANIT ? i + 1 : 0; + return i < ANIT - 1 ? i + 1 : 0; } int R_get_special_id (int n) { @@ -1669,7 +1755,7 @@ void R_load (char s[8], int f) { }; } else if (strncasecmp(s, "_WATER_", 7) == 0) { walp[max_textures] = (image) { - .n = (void*)(s[7] - '0' + 1), + .n = (void*)((intptr_t)s[7] - '0' + 1), .x = 0, .y = 0, .w = 8, @@ -1718,9 +1804,8 @@ void R_end_load (void) { void R_loadsky (int sky) { char s[6]; - logo("R_loadsky(%i)\n", sky); strcpy(s, "RSKYx"); s[4] = '0' + sky; R_gl_free_image(&horiz); horiz = R_gl_loadimage(s); -} \ No newline at end of file +}