static void drawTextureDisplay (void) { struct TexSquare *square = texgrid; int x, y; glColor4f(1.0,1.0,1.0,1.0); if (is_yuv) glEnableYUVConversion(GL_TEXTURE_2D, use_yuv); for (y = 0; y < texnumy; y++) { int thish = texture_height; if (y == texnumy - 1 && image_height % texture_height) thish = image_height % texture_height; for (x = 0; x < texnumx; x++) { int thisw = texture_width; if (x == texnumx - 1 && image_width % texture_width) thisw = image_width % texture_width; glBindTexture (GL_TEXTURE_2D, square->texobj); if (is_yuv) { mpglActiveTexture(GL_TEXTURE1); glBindTexture (GL_TEXTURE_2D, square->uvtexobjs[0]); mpglActiveTexture(GL_TEXTURE2); glBindTexture (GL_TEXTURE_2D, square->uvtexobjs[1]); mpglActiveTexture(GL_TEXTURE0); } if (texdirty) { glUploadTex(GL_TEXTURE_2D, gl_bitmap_format, gl_bitmap_type, square->texture, image_width * image_bytes, 0, 0, thisw, thish, 0); } glDrawTex(square->fx, square->fy, square->fw, square->fh, 0, 0, texture_width, texture_height, texture_width, texture_height, 0, is_yuv, 0, 0); square++; } /* for all texnumx */ } /* for all texnumy */ if (is_yuv) glDisableYUVConversion(GL_TEXTURE_2D, use_yuv); texdirty = 0; }
/** * Creates the textures and the display list needed for displaying * an OSD part. * Callback function for vo_draw_text(). */ static void create_osd_texture(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) { // initialize to 8 to avoid special-casing on alignment int sx = 8, sy = 8; GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST; if (w <= 0 || h <= 0 || stride < w) { mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n"); return; } texSize(w, h, &sx, &sy); if (osdtexCnt >= MAX_OSD_PARTS) { mp_msg(MSGT_VO, MSGL_ERR, "Too many OSD parts, contact the developers!\n"); return; } // create Textures for OSD part mpglGenTextures(1, &osdtex[osdtexCnt]); mpglBindTexture(gl_target, osdtex[osdtexCnt]); glCreateClearTex(gl_target, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0); glUploadTex(gl_target, GL_LUMINANCE, GL_UNSIGNED_BYTE, src, stride, 0, 0, w, h, 0); #ifndef FAST_OSD mpglGenTextures(1, &osdatex[osdtexCnt]); mpglBindTexture(gl_target, osdatex[osdtexCnt]); glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0); { int i; char *tmp = malloc(stride * h); // convert alpha from weird MPlayer scale. // in-place is not possible since it is reused for future OSDs for (i = h * stride - 1; i >= 0; i--) tmp[i] = -srca[i]; glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, tmp, stride, 0, 0, w, h, 0); free(tmp); } #endif mpglBindTexture(gl_target, 0); // Create a list for rendering this OSD part #ifndef FAST_OSD osdaDispList[osdtexCnt] = mpglGenLists(1); mpglNewList(osdaDispList[osdtexCnt], GL_COMPILE); // render alpha mpglBindTexture(gl_target, osdatex[osdtexCnt]); glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0); mpglEndList(); #endif osdDispList[osdtexCnt] = mpglGenLists(1); mpglNewList(osdDispList[osdtexCnt], GL_COMPILE); // render OSD mpglBindTexture(gl_target, osdtex[osdtexCnt]); glDrawTex(x0, y0, w, h, 0, 0, w, h, sx, sy, use_rectangle == 1, 0, 0); mpglEndList(); osdtexCnt++; }
/** * \brief construct display list from ass image list * \param img image list to create OSD from. * A value of NULL has the same effect as clearEOSD() */ static void genEOSD(struct mp_eosd_image_list *imgs) { int sx, sy; int tinytexcur = 0; int smalltexcur = 0; GLuint *curtex; GLint scale_type = scaled_osd ? GL_LINEAR : GL_NEAREST; struct mp_eosd_image *img = eosd_image_first(imgs); struct mp_eosd_image *i; if (imgs->changed == 0) // there are elements, but they are unchanged return; if (img && imgs->changed == 1) // there are elements, but they just moved goto skip_upload; clearEOSD(); if (!img) return; if (!largeeosdtex[0]) { mpglGenTextures(2, largeeosdtex); mpglBindTexture(gl_target, largeeosdtex[0]); glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0); mpglBindTexture(gl_target, largeeosdtex[1]); glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, LARGE_EOSD_TEX_SIZE, LARGE_EOSD_TEX_SIZE, 0); } for (i = img; i; i = eosd_image_next(imgs)) { if (i->w <= 0 || i->h <= 0 || i->stride < i->w) continue; if (is_tinytex(i, tinytexcur)) tinytexcur++; else if (is_smalltex(i, smalltexcur)) smalltexcur++; else eosdtexCnt++; } mp_msg(MSGT_VO, MSGL_DBG2, "EOSD counts (tiny, small, all): %i, %i, %i\n", tinytexcur, smalltexcur, eosdtexCnt); if (eosdtexCnt) { eosdtex = calloc(eosdtexCnt, sizeof(GLuint)); mpglGenTextures(eosdtexCnt, eosdtex); } tinytexcur = smalltexcur = 0; for (i = eosd_image_first(imgs), curtex = eosdtex; i; i = eosd_image_next(imgs)) { int x = 0, y = 0; if (i->w <= 0 || i->h <= 0 || i->stride < i->w) { mp_msg(MSGT_VO, MSGL_V, "Invalid dimensions OSD for part!\n"); continue; } if (is_tinytex(i, tinytexcur)) { tinytex_pos(tinytexcur, &x, &y); mpglBindTexture(gl_target, largeeosdtex[0]); tinytexcur++; } else if (is_smalltex(i, smalltexcur)) { smalltex_pos(smalltexcur, &x, &y); mpglBindTexture(gl_target, largeeosdtex[1]); smalltexcur++; } else { texSize(i->w, i->h, &sx, &sy); mpglBindTexture(gl_target, *curtex++); glCreateClearTex(gl_target, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, scale_type, sx, sy, 0); } glUploadTex(gl_target, GL_ALPHA, GL_UNSIGNED_BYTE, i->bitmap, i->stride, x, y, i->w, i->h, 0); } eosdDispList = mpglGenLists(1); skip_upload: mpglNewList(eosdDispList, GL_COMPILE); tinytexcur = smalltexcur = 0; for (i = eosd_image_first(imgs), curtex = eosdtex; i; i = eosd_image_next(imgs)) { int x = 0, y = 0; if (i->w <= 0 || i->h <= 0 || i->stride < i->w) continue; mpglColor4ub(i->color >> 24, (i->color >> 16) & 0xff, (i->color >> 8) & 0xff, 255 - (i->color & 0xff)); if (is_tinytex(i, tinytexcur)) { tinytex_pos(tinytexcur, &x, &y); sx = sy = LARGE_EOSD_TEX_SIZE; mpglBindTexture(gl_target, largeeosdtex[0]); tinytexcur++; } else if (is_smalltex(i, smalltexcur)) { smalltex_pos(smalltexcur, &x, &y); sx = sy = LARGE_EOSD_TEX_SIZE; mpglBindTexture(gl_target, largeeosdtex[1]); smalltexcur++; } else { texSize(i->w, i->h, &sx, &sy); mpglBindTexture(gl_target, *curtex++); } glDrawTex(i->dst_x, i->dst_y, i->w, i->h, x, y, i->w, i->h, sx, sy, use_rectangle == 1, 0, 0); } mpglEndList(); mpglBindTexture(gl_target, 0); }