vo_sdl: some OSD optimizations

The premultiplied-alpha hack is changed:

- The first stage now uses a colormod of black with an unmodified
  texture. This saves on applying the AND mask of 0xFF000000 to keep
  alpha only.

- The second stage no longer uses an AND mask, but only an OR mask of
  0xFF000000 to cancel out alpha.

- The texture uploads are no longer done using SDL_LockTexture,
  SDL_ConvertPixels, SDL_UnlockTexture when the mpv pixel format matches
  the OSD's pixel format. Instead, SDL_UploadTexture is used, which
  saves a copy when using the "opengl" renderer.
This commit is contained in:
Rudolf Polzer 2012-12-28 14:27:03 +01:00
parent 0db55cd86a
commit a313af3d02
1 changed files with 41 additions and 23 deletions

View File

@ -61,7 +61,7 @@ const struct formatmap_entry formats[] = {
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
{SDL_PIXELFORMAT_RGBX8888, IMGFMT_RGBA, 0}, // has no alpha -> bad for OSD {SDL_PIXELFORMAT_RGBX8888, IMGFMT_RGBA, 0}, // has no alpha -> bad for OSD
{SDL_PIXELFORMAT_BGRX8888, IMGFMT_BGRA, 0}, // has no alpha -> bad for OSD {SDL_PIXELFORMAT_BGRX8888, IMGFMT_BGRA, 0}, // has no alpha -> bad for OSD
{SDL_PIXELFORMAT_ARGB8888, IMGFMT_ARGB, 1}, {SDL_PIXELFORMAT_ARGB8888, IMGFMT_ARGB, 1}, // matches SUBBITMAP_RGBA
{SDL_PIXELFORMAT_RGBA8888, IMGFMT_RGBA, 1}, {SDL_PIXELFORMAT_RGBA8888, IMGFMT_RGBA, 1},
{SDL_PIXELFORMAT_ABGR8888, IMGFMT_ABGR, 1}, {SDL_PIXELFORMAT_ABGR8888, IMGFMT_ABGR, 1},
{SDL_PIXELFORMAT_BGRA8888, IMGFMT_BGRA, 1}, {SDL_PIXELFORMAT_BGRA8888, IMGFMT_BGRA, 1},
@ -77,7 +77,7 @@ const struct formatmap_entry formats[] = {
#else #else
{SDL_PIXELFORMAT_RGBX8888, IMGFMT_ABGR, 0}, // has no alpha -> bad for OSD {SDL_PIXELFORMAT_RGBX8888, IMGFMT_ABGR, 0}, // has no alpha -> bad for OSD
{SDL_PIXELFORMAT_BGRX8888, IMGFMT_ARGB, 0}, // has no alpha -> bad for OSD {SDL_PIXELFORMAT_BGRX8888, IMGFMT_ARGB, 0}, // has no alpha -> bad for OSD
{SDL_PIXELFORMAT_ARGB8888, IMGFMT_BGRA, 1}, {SDL_PIXELFORMAT_ARGB8888, IMGFMT_BGRA, 1}, // matches SUBBITMAP_RGBA
{SDL_PIXELFORMAT_RGBA8888, IMGFMT_ABGR, 1}, {SDL_PIXELFORMAT_RGBA8888, IMGFMT_ABGR, 1},
{SDL_PIXELFORMAT_ABGR8888, IMGFMT_RGBA, 1}, {SDL_PIXELFORMAT_ABGR8888, IMGFMT_RGBA, 1},
{SDL_PIXELFORMAT_BGRA8888, IMGFMT_ARGB, 1}, {SDL_PIXELFORMAT_BGRA8888, IMGFMT_ARGB, 1},
@ -561,39 +561,57 @@ static void uninit(struct vo *vo)
talloc_free(vc); talloc_free(vc);
} }
static void subbitmap_to_texture(struct vo *vo, SDL_Texture *tex, static inline void upload_to_texture(struct vo *vo, SDL_Texture *tex,
struct sub_bitmap *bmp, int w, int h, void *bitmap, int stride)
uint32_t andmask, uint32_t ormask)
{ {
struct priv *vc = vo->priv; struct priv *vc = vo->priv;
uint32_t *temppixels; if (vc->osd_format.sdl == SDL_PIXELFORMAT_ARGB8888) {
temppixels = talloc_array(vo, uint32_t, bmp->w * bmp->h); // NOTE: this optimization is questionable, because SDL docs say
// that this way is slow.
// apply pixel masks // It did measure up faster, though...
int x, y; SDL_UpdateTexture(tex, NULL, bitmap, stride);
for (y = 0; y < bmp->h; ++y) { return;
const uint32_t *src =
(const uint32_t *) ((const char *) bmp->bitmap + y * bmp->stride);
uint32_t *dst = temppixels + y * bmp->w;
for (x = 0; x < bmp->w; ++x)
dst[x] = (src[x] & andmask) | ormask;
} }
// convert to SDL's format and upload
void *pixels; void *pixels;
int pitch; int pitch;
if (SDL_LockTexture(tex, NULL, &pixels, &pitch)) { if (SDL_LockTexture(tex, NULL, &pixels, &pitch)) {
mp_msg(MSGT_VO, MSGL_ERR, "[sdl] Could not lock texture\n"); mp_msg(MSGT_VO, MSGL_ERR, "[sdl] Could not lock texture\n");
} else { } else {
SDL_ConvertPixels(bmp->w, bmp->h, SDL_PIXELFORMAT_ARGB8888, SDL_ConvertPixels(w, h, SDL_PIXELFORMAT_ARGB8888,
temppixels, sizeof(uint32_t) * bmp->w, bitmap, stride,
vc->osd_format.sdl, vc->osd_format.sdl,
pixels, pitch); pixels, pitch);
SDL_UnlockTexture(tex); SDL_UnlockTexture(tex);
} }
}
talloc_free(temppixels); static inline void subbitmap_to_texture(struct vo *vo, SDL_Texture *tex,
struct sub_bitmap *bmp,
uint32_t ormask)
{
if (ormask == 0) {
upload_to_texture(vo, tex, bmp->w, bmp->h,
bmp->bitmap, bmp->stride);
} else {
uint32_t *temppixels;
temppixels = talloc_array(vo, uint32_t, bmp->w * bmp->h);
int x, y;
for (y = 0; y < bmp->h; ++y) {
const uint32_t *src =
(const uint32_t *) ((const char *) bmp->bitmap + y * bmp->stride);
uint32_t *dst = temppixels + y * bmp->w;
for (x = 0; x < bmp->w; ++x)
dst[x] = src[x] | ormask;
}
upload_to_texture(vo, tex, bmp->w, bmp->h,
temppixels, sizeof(uint32_t) * bmp->w);
talloc_free(temppixels);
}
} }
static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs) static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
@ -643,8 +661,8 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
if (target->tex) { if (target->tex) {
SDL_SetTextureBlendMode(target->tex, SDL_SetTextureBlendMode(target->tex,
SDL_BLENDMODE_BLEND); SDL_BLENDMODE_BLEND);
subbitmap_to_texture(vo, target->tex, bmp, SDL_SetTextureColorMod(target->tex, 0, 0, 0);
0xFF000000, 0x00000000); // RGBA -> 000A subbitmap_to_texture(vo, target->tex, bmp, 0); // RGBA -> 000A
} }
// tex2: added texture // tex2: added texture
@ -663,7 +681,7 @@ static void generate_osd_part(struct vo *vo, struct sub_bitmaps *imgs)
SDL_SetTextureBlendMode(target->tex2, SDL_SetTextureBlendMode(target->tex2,
SDL_BLENDMODE_ADD); SDL_BLENDMODE_ADD);
subbitmap_to_texture(vo, target->tex2, bmp, subbitmap_to_texture(vo, target->tex2, bmp,
0x00FFFFFF, 0xFF000000); // RGBA -> RGB1 0xFF000000); // RGBA -> RGB1
} }
} }
} }