Initial pass at shader YV12 support - doesn't quite work yet.
authorSam Lantinga <slouken@libsdl.org>
Sat, 12 Feb 2011 00:25:02 -0800
changeset 52647ace5f8f432f
parent 5263 e1122f31fec5
child 5265 48724afcdc6e
Initial pass at shader YV12 support - doesn't quite work yet.
include/SDL_pixels.h
src/render/opengl/SDL_render_gl.c
test/testoverlay2.c
     1.1 --- a/include/SDL_pixels.h	Fri Feb 11 23:02:35 2011 -0800
     1.2 +++ b/include/SDL_pixels.h	Sat Feb 12 00:25:02 2011 -0800
     1.3 @@ -124,9 +124,7 @@
     1.4  #define SDL_BITSPERPIXEL(X)	(((X) >> 8) & 0xFF)
     1.5  #define SDL_BYTESPERPIXEL(X) \
     1.6      (SDL_ISPIXELFORMAT_FOURCC(X) ? \
     1.7 -        ((((X) == SDL_PIXELFORMAT_YV12) || \
     1.8 -          ((X) == SDL_PIXELFORMAT_IYUV) || \
     1.9 -          ((X) == SDL_PIXELFORMAT_YUY2) || \
    1.10 +        ((((X) == SDL_PIXELFORMAT_YUY2) || \
    1.11            ((X) == SDL_PIXELFORMAT_UYVY) || \
    1.12            ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
    1.13  
     2.1 --- a/src/render/opengl/SDL_render_gl.c	Fri Feb 11 23:02:35 2011 -0800
     2.2 +++ b/src/render/opengl/SDL_render_gl.c	Sat Feb 12 00:25:02 2011 -0800
     2.3 @@ -119,6 +119,11 @@
     2.4      void *pixels;
     2.5      int pitch;
     2.6      SDL_Rect locked_rect;
     2.7 +
     2.8 +    /* YV12 texture support */
     2.9 +    SDL_bool yuv;
    2.10 +    GLuint utexture;
    2.11 +    GLuint vtexture;
    2.12  } GL_TextureData;
    2.13  
    2.14  
    2.15 @@ -292,12 +297,11 @@
    2.16      SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
    2.17                  data->shaders ? "ENABLED" : "DISABLED");
    2.18  
    2.19 -#if 0
    2.20      /* We support YV12 textures using 3 textures and a shader */
    2.21      if (data->shaders && data->num_texture_units >= 3) {
    2.22          renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
    2.23 +        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
    2.24      }
    2.25 -#endif
    2.26  
    2.27      /* Set up parameters for rendering */
    2.28      data->blendMode = -1;
    2.29 @@ -372,6 +376,12 @@
    2.30          *format = GL_BGRA;
    2.31          *type = GL_UNSIGNED_INT_8_8_8_8_REV;
    2.32          break;
    2.33 +    case SDL_PIXELFORMAT_YV12:
    2.34 +    case SDL_PIXELFORMAT_IYUV:
    2.35 +        *internalFormat = GL_LUMINANCE;
    2.36 +        *format = GL_LUMINANCE;
    2.37 +        *type = GL_UNSIGNED_BYTE;
    2.38 +        break;
    2.39      default:
    2.40          return SDL_FALSE;
    2.41      }
    2.42 @@ -404,8 +414,15 @@
    2.43      }
    2.44  
    2.45      if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
    2.46 +        size_t size;
    2.47          data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
    2.48 -        data->pixels = SDL_malloc(texture->h * data->pitch);
    2.49 +        size = texture->h * data->pitch;
    2.50 +        if (texture->format == SDL_PIXELFORMAT_YV12 ||
    2.51 +            texture->format == SDL_PIXELFORMAT_IYUV) {
    2.52 +            /* Need to add size for the U and V planes */
    2.53 +            size += (2 * (texture->h * data->pitch) / 4);
    2.54 +        }
    2.55 +        data->pixels = SDL_malloc(size);
    2.56          if (!data->pixels) {
    2.57              SDL_OutOfMemory();
    2.58              SDL_free(data);
    2.59 @@ -478,6 +495,41 @@
    2.60          GL_SetError("glTexImage2D()", result);
    2.61          return -1;
    2.62      }
    2.63 +
    2.64 +    if (texture->format == SDL_PIXELFORMAT_YV12 ||
    2.65 +        texture->format == SDL_PIXELFORMAT_IYUV) {
    2.66 +        data->yuv = SDL_TRUE;
    2.67 +
    2.68 +        renderdata->glGenTextures(1, &data->utexture);
    2.69 +        renderdata->glGenTextures(1, &data->vtexture);
    2.70 +        renderdata->glEnable(data->type);
    2.71 +
    2.72 +        renderdata->glBindTexture(data->type, data->utexture);
    2.73 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    2.74 +                                    GL_LINEAR);
    2.75 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    2.76 +                                    GL_LINEAR);
    2.77 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    2.78 +                                    GL_CLAMP_TO_EDGE);
    2.79 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    2.80 +                                    GL_CLAMP_TO_EDGE);
    2.81 +        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
    2.82 +                                 texture_h/2, 0, format, type, NULL);
    2.83 +
    2.84 +        renderdata->glBindTexture(data->type, data->vtexture);
    2.85 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    2.86 +                                    GL_LINEAR);
    2.87 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    2.88 +                                    GL_LINEAR);
    2.89 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    2.90 +                                    GL_CLAMP_TO_EDGE);
    2.91 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    2.92 +                                    GL_CLAMP_TO_EDGE);
    2.93 +        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
    2.94 +                                 texture_h/2, 0, format, type, NULL);
    2.95 +
    2.96 +        renderdata->glDisable(data->type);
    2.97 +    }
    2.98      return 0;
    2.99  }
   2.100  
   2.101 @@ -500,6 +552,35 @@
   2.102      renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   2.103                                  rect->h, data->format, data->formattype,
   2.104                                  pixels);
   2.105 +    if (data->yuv) {
   2.106 +        /* Skip to the top of the next texture */
   2.107 +        const void *top = (const void*)((const Uint8*)pixels + (texture->h-rect->y) * pitch - rect->x);
   2.108 +
   2.109 +        /* Skip to the correct offset into the next texture */
   2.110 +        pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
   2.111 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
   2.112 +            renderdata->glBindTexture(data->type, data->vtexture);
   2.113 +        } else {
   2.114 +            renderdata->glBindTexture(data->type, data->utexture);
   2.115 +        }
   2.116 +        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   2.117 +                                    rect->w/2, rect->h/2,
   2.118 +                                    data->format, data->formattype, pixels);
   2.119 +
   2.120 +        /* Skip to the top of the next texture */
   2.121 +        top = (const void*)((const Uint8*)top + (texture->h * pitch)/4);
   2.122 +
   2.123 +        /* Skip to the correct offset into the next texture */
   2.124 +        pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
   2.125 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
   2.126 +            renderdata->glBindTexture(data->type, data->utexture);
   2.127 +        } else {
   2.128 +            renderdata->glBindTexture(data->type, data->vtexture);
   2.129 +        }
   2.130 +        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   2.131 +                                    rect->w/2, rect->h/2,
   2.132 +                                    data->format, data->formattype, pixels);
   2.133 +    }
   2.134      renderdata->glDisable(data->type);
   2.135      result = renderdata->glGetError();
   2.136      if (result != GL_NO_ERROR) {
   2.137 @@ -750,6 +831,13 @@
   2.138      maxv *= texturedata->texh;
   2.139  
   2.140      data->glEnable(texturedata->type);
   2.141 +    if (texturedata->yuv) {
   2.142 +        data->glActiveTextureARB(GL_TEXTURE2_ARB);
   2.143 +        data->glBindTexture(texturedata->type, texturedata->vtexture);
   2.144 +        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   2.145 +        data->glBindTexture(texturedata->type, texturedata->utexture);
   2.146 +        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   2.147 +    }
   2.148      data->glBindTexture(texturedata->type, texturedata->texture);
   2.149  
   2.150      if (texture->modMode) {
   2.151 @@ -762,7 +850,11 @@
   2.152      }
   2.153  
   2.154      GL_SetBlendMode(data, texture->blendMode);
   2.155 -    GL_SelectShader(data->shaders, SHADER_RGB);
   2.156 +    if (texturedata->yuv) {
   2.157 +        GL_SelectShader(data->shaders, SHADER_YV12);
   2.158 +    } else {
   2.159 +        GL_SelectShader(data->shaders, SHADER_RGB);
   2.160 +    }
   2.161  
   2.162      data->glBegin(GL_TRIANGLE_STRIP);
   2.163      data->glTexCoord2f(minu, minv);
   2.164 @@ -848,6 +940,10 @@
   2.165      if (data->texture) {
   2.166          renderdata->glDeleteTextures(1, &data->texture);
   2.167      }
   2.168 +    if (data->yuv) {
   2.169 +        renderdata->glDeleteTextures(1, &data->utexture);
   2.170 +        renderdata->glDeleteTextures(1, &data->vtexture);
   2.171 +    }
   2.172      if (data->pixels) {
   2.173          SDL_free(data->pixels);
   2.174      }
     3.1 --- a/test/testoverlay2.c	Fri Feb 11 23:02:35 2011 -0800
     3.2 +++ b/test/testoverlay2.c	Sat Feb 12 00:25:02 2011 -0800
     3.3 @@ -360,7 +360,7 @@
     3.4      int fps = 12;
     3.5      int fpsdelay;
     3.6      int nodelay = 0;
     3.7 -    int overlay_format = SDL_YUY2_OVERLAY;
     3.8 +    Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
     3.9      int scale = 5;
    3.10      SDL_bool done = SDL_FALSE;
    3.11  
    3.12 @@ -397,15 +397,15 @@
    3.13          } else if (strcmp(argv[1], "-format") == 0) {
    3.14              if (argv[2]) {
    3.15                  if (!strcmp(argv[2], "YV12"))
    3.16 -                    overlay_format = SDL_YV12_OVERLAY;
    3.17 +                    pixel_format = SDL_PIXELFORMAT_YV12;
    3.18                  else if (!strcmp(argv[2], "IYUV"))
    3.19 -                    overlay_format = SDL_IYUV_OVERLAY;
    3.20 +                    pixel_format = SDL_PIXELFORMAT_IYUV;
    3.21                  else if (!strcmp(argv[2], "YUY2"))
    3.22 -                    overlay_format = SDL_YUY2_OVERLAY;
    3.23 +                    pixel_format = SDL_PIXELFORMAT_YUY2;
    3.24                  else if (!strcmp(argv[2], "UYVY"))
    3.25 -                    overlay_format = SDL_UYVY_OVERLAY;
    3.26 +                    pixel_format = SDL_PIXELFORMAT_UYVY;
    3.27                  else if (!strcmp(argv[2], "YVYU"))
    3.28 -                    overlay_format = SDL_YVYU_OVERLAY;
    3.29 +                    pixel_format = SDL_PIXELFORMAT_YVYU;
    3.30                  else {
    3.31                      fprintf(stderr,
    3.32                              "The -format option %s is not recognized, see help for info.\n",
    3.33 @@ -490,7 +490,7 @@
    3.34          quit(4);
    3.35      }
    3.36  
    3.37 -    MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H);
    3.38 +    MooseTexture = SDL_CreateTexture(renderer, pixel_format, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H);
    3.39      if (!MooseTexture) {
    3.40          fprintf(stderr, "Couldn't set create texture: %s\n", SDL_GetError());
    3.41          free(RawMooseData);
    3.42 @@ -569,7 +569,7 @@
    3.43          if (!paused) {
    3.44              i = (i + 1) % MOOSEFRAMES_COUNT;
    3.45  
    3.46 -            SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*2);
    3.47 +            SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*SDL_BYTESPERPIXEL(pixel_format));
    3.48          }
    3.49          SDL_RenderClear(renderer);
    3.50          SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect);