src/render/opengl/SDL_render_gl.c
changeset 5264 7ace5f8f432f
parent 5262 b530ef003506
child 5265 48724afcdc6e
     1.1 --- a/src/render/opengl/SDL_render_gl.c	Fri Feb 11 23:02:35 2011 -0800
     1.2 +++ b/src/render/opengl/SDL_render_gl.c	Sat Feb 12 00:25:02 2011 -0800
     1.3 @@ -119,6 +119,11 @@
     1.4      void *pixels;
     1.5      int pitch;
     1.6      SDL_Rect locked_rect;
     1.7 +
     1.8 +    /* YV12 texture support */
     1.9 +    SDL_bool yuv;
    1.10 +    GLuint utexture;
    1.11 +    GLuint vtexture;
    1.12  } GL_TextureData;
    1.13  
    1.14  
    1.15 @@ -292,12 +297,11 @@
    1.16      SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
    1.17                  data->shaders ? "ENABLED" : "DISABLED");
    1.18  
    1.19 -#if 0
    1.20      /* We support YV12 textures using 3 textures and a shader */
    1.21      if (data->shaders && data->num_texture_units >= 3) {
    1.22          renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
    1.23 +        renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
    1.24      }
    1.25 -#endif
    1.26  
    1.27      /* Set up parameters for rendering */
    1.28      data->blendMode = -1;
    1.29 @@ -372,6 +376,12 @@
    1.30          *format = GL_BGRA;
    1.31          *type = GL_UNSIGNED_INT_8_8_8_8_REV;
    1.32          break;
    1.33 +    case SDL_PIXELFORMAT_YV12:
    1.34 +    case SDL_PIXELFORMAT_IYUV:
    1.35 +        *internalFormat = GL_LUMINANCE;
    1.36 +        *format = GL_LUMINANCE;
    1.37 +        *type = GL_UNSIGNED_BYTE;
    1.38 +        break;
    1.39      default:
    1.40          return SDL_FALSE;
    1.41      }
    1.42 @@ -404,8 +414,15 @@
    1.43      }
    1.44  
    1.45      if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
    1.46 +        size_t size;
    1.47          data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
    1.48 -        data->pixels = SDL_malloc(texture->h * data->pitch);
    1.49 +        size = texture->h * data->pitch;
    1.50 +        if (texture->format == SDL_PIXELFORMAT_YV12 ||
    1.51 +            texture->format == SDL_PIXELFORMAT_IYUV) {
    1.52 +            /* Need to add size for the U and V planes */
    1.53 +            size += (2 * (texture->h * data->pitch) / 4);
    1.54 +        }
    1.55 +        data->pixels = SDL_malloc(size);
    1.56          if (!data->pixels) {
    1.57              SDL_OutOfMemory();
    1.58              SDL_free(data);
    1.59 @@ -478,6 +495,41 @@
    1.60          GL_SetError("glTexImage2D()", result);
    1.61          return -1;
    1.62      }
    1.63 +
    1.64 +    if (texture->format == SDL_PIXELFORMAT_YV12 ||
    1.65 +        texture->format == SDL_PIXELFORMAT_IYUV) {
    1.66 +        data->yuv = SDL_TRUE;
    1.67 +
    1.68 +        renderdata->glGenTextures(1, &data->utexture);
    1.69 +        renderdata->glGenTextures(1, &data->vtexture);
    1.70 +        renderdata->glEnable(data->type);
    1.71 +
    1.72 +        renderdata->glBindTexture(data->type, data->utexture);
    1.73 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    1.74 +                                    GL_LINEAR);
    1.75 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    1.76 +                                    GL_LINEAR);
    1.77 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    1.78 +                                    GL_CLAMP_TO_EDGE);
    1.79 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    1.80 +                                    GL_CLAMP_TO_EDGE);
    1.81 +        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
    1.82 +                                 texture_h/2, 0, format, type, NULL);
    1.83 +
    1.84 +        renderdata->glBindTexture(data->type, data->vtexture);
    1.85 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    1.86 +                                    GL_LINEAR);
    1.87 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    1.88 +                                    GL_LINEAR);
    1.89 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    1.90 +                                    GL_CLAMP_TO_EDGE);
    1.91 +        renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    1.92 +                                    GL_CLAMP_TO_EDGE);
    1.93 +        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
    1.94 +                                 texture_h/2, 0, format, type, NULL);
    1.95 +
    1.96 +        renderdata->glDisable(data->type);
    1.97 +    }
    1.98      return 0;
    1.99  }
   1.100  
   1.101 @@ -500,6 +552,35 @@
   1.102      renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
   1.103                                  rect->h, data->format, data->formattype,
   1.104                                  pixels);
   1.105 +    if (data->yuv) {
   1.106 +        /* Skip to the top of the next texture */
   1.107 +        const void *top = (const void*)((const Uint8*)pixels + (texture->h-rect->y) * pitch - rect->x);
   1.108 +
   1.109 +        /* Skip to the correct offset into the next texture */
   1.110 +        pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
   1.111 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
   1.112 +            renderdata->glBindTexture(data->type, data->vtexture);
   1.113 +        } else {
   1.114 +            renderdata->glBindTexture(data->type, data->utexture);
   1.115 +        }
   1.116 +        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.117 +                                    rect->w/2, rect->h/2,
   1.118 +                                    data->format, data->formattype, pixels);
   1.119 +
   1.120 +        /* Skip to the top of the next texture */
   1.121 +        top = (const void*)((const Uint8*)top + (texture->h * pitch)/4);
   1.122 +
   1.123 +        /* Skip to the correct offset into the next texture */
   1.124 +        pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
   1.125 +        if (texture->format == SDL_PIXELFORMAT_YV12) {
   1.126 +            renderdata->glBindTexture(data->type, data->utexture);
   1.127 +        } else {
   1.128 +            renderdata->glBindTexture(data->type, data->vtexture);
   1.129 +        }
   1.130 +        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
   1.131 +                                    rect->w/2, rect->h/2,
   1.132 +                                    data->format, data->formattype, pixels);
   1.133 +    }
   1.134      renderdata->glDisable(data->type);
   1.135      result = renderdata->glGetError();
   1.136      if (result != GL_NO_ERROR) {
   1.137 @@ -750,6 +831,13 @@
   1.138      maxv *= texturedata->texh;
   1.139  
   1.140      data->glEnable(texturedata->type);
   1.141 +    if (texturedata->yuv) {
   1.142 +        data->glActiveTextureARB(GL_TEXTURE2_ARB);
   1.143 +        data->glBindTexture(texturedata->type, texturedata->vtexture);
   1.144 +        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   1.145 +        data->glBindTexture(texturedata->type, texturedata->utexture);
   1.146 +        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   1.147 +    }
   1.148      data->glBindTexture(texturedata->type, texturedata->texture);
   1.149  
   1.150      if (texture->modMode) {
   1.151 @@ -762,7 +850,11 @@
   1.152      }
   1.153  
   1.154      GL_SetBlendMode(data, texture->blendMode);
   1.155 -    GL_SelectShader(data->shaders, SHADER_RGB);
   1.156 +    if (texturedata->yuv) {
   1.157 +        GL_SelectShader(data->shaders, SHADER_YV12);
   1.158 +    } else {
   1.159 +        GL_SelectShader(data->shaders, SHADER_RGB);
   1.160 +    }
   1.161  
   1.162      data->glBegin(GL_TRIANGLE_STRIP);
   1.163      data->glTexCoord2f(minu, minv);
   1.164 @@ -848,6 +940,10 @@
   1.165      if (data->texture) {
   1.166          renderdata->glDeleteTextures(1, &data->texture);
   1.167      }
   1.168 +    if (data->yuv) {
   1.169 +        renderdata->glDeleteTextures(1, &data->utexture);
   1.170 +        renderdata->glDeleteTextures(1, &data->vtexture);
   1.171 +    }
   1.172      if (data->pixels) {
   1.173          SDL_free(data->pixels);
   1.174      }