X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgl%2Frender.c;h=b5da71f4c4949fe01456cc8fb2677e08866919f1;hb=b7c39e0d9229a7616c63cf545cdd9576b9bf3e2c;hp=6b62793494c418920d95a9206420ceba7e3c1aae;hpb=f333581fff4a1ef2f4d4af740f6a175c8c6dec91;p=flatwaifu.git diff --git a/src/gl/render.c b/src/gl/render.c index 6b62793..b5da71f 100644 --- a/src/gl/render.c +++ b/src/gl/render.c @@ -57,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; @@ -82,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 */ @@ -180,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, @@ -193,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, @@ -210,6 +216,50 @@ 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; @@ -219,40 +269,52 @@ static cache *R_cache_new (void) { 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; @@ -264,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 */ @@ -425,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); @@ -435,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; } @@ -453,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) { @@ -475,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); @@ -483,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); } } @@ -507,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) { @@ -769,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 { @@ -781,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) { @@ -1086,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); @@ -1121,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); } @@ -1146,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(); @@ -1165,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); } } @@ -1196,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); } @@ -1316,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) { @@ -1598,7 +1680,7 @@ void R_init (void) { } void R_done (void) { - // do nothing + R_cache_free(root, 1); } void R_setgamma (int g) { @@ -1722,7 +1804,6 @@ 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);