src/render/SDL_render.c
changeset 5156 307ccc9c135e
parent 5154 fb424691cfc7
child 5157 657543cc92f9
     1.1 --- a/src/render/SDL_render.c	Wed Feb 02 22:55:12 2011 -0800
     1.2 +++ b/src/render/SDL_render.c	Thu Feb 03 00:19:40 2011 -0800
     1.3 @@ -152,6 +152,34 @@
     1.4      return 0;
     1.5  }
     1.6  
     1.7 +static SDL_bool
     1.8 +IsSupportedFormat(SDL_Renderer * renderer, Uint32 format)
     1.9 +{
    1.10 +    Uint32 i;
    1.11 +
    1.12 +    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.13 +        if (renderer->info.texture_formats[i] == format) {
    1.14 +            return SDL_TRUE;
    1.15 +        }
    1.16 +    }
    1.17 +    return SDL_FALSE;
    1.18 +}
    1.19 +
    1.20 +static Uint32
    1.21 +GetClosestSupportedFormat(SDL_Renderer * renderer, Uint32 format)
    1.22 +{
    1.23 +    Uint32 i;
    1.24 +    SDL_bool hasAlpha = SDL_ISPIXELFORMAT_ALPHA(format);
    1.25 +
    1.26 +    /* We just want to match the first format that has the same channels */
    1.27 +    for (i = 0; i < renderer->info.num_texture_formats; ++i) {
    1.28 +        if (SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == hasAlpha) {
    1.29 +            return renderer->info.texture_formats[i];
    1.30 +        }
    1.31 +    }
    1.32 +    return renderer->info.texture_formats[0];
    1.33 +}
    1.34 +
    1.35  SDL_Texture *
    1.36  SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
    1.37  {
    1.38 @@ -159,14 +187,18 @@
    1.39  
    1.40      CHECK_RENDERER_MAGIC(renderer, NULL);
    1.41  
    1.42 +    if (SDL_ISPIXELFORMAT_INDEXED(format)) {
    1.43 +        SDL_SetError("Palettized textures are not supported");
    1.44 +        return NULL;
    1.45 +    }
    1.46      if (w <= 0 || h <= 0) {
    1.47          SDL_SetError("Texture dimensions can't be 0");
    1.48 -        return 0;
    1.49 +        return NULL;
    1.50      }
    1.51      texture = (SDL_Texture *) SDL_calloc(1, sizeof(*texture));
    1.52      if (!texture) {
    1.53          SDL_OutOfMemory();
    1.54 -        return 0;
    1.55 +        return NULL;
    1.56      }
    1.57      texture->magic = &texture_magic;
    1.58      texture->format = format;
    1.59 @@ -184,9 +216,35 @@
    1.60      }
    1.61      renderer->textures = texture;
    1.62  
    1.63 -    if (renderer->CreateTexture(renderer, texture) < 0) {
    1.64 -        SDL_DestroyTexture(texture);
    1.65 -        return 0;
    1.66 +    if (IsSupportedFormat(renderer, format)) {
    1.67 +        if (renderer->CreateTexture(renderer, texture) < 0) {
    1.68 +            SDL_DestroyTexture(texture);
    1.69 +            return 0;
    1.70 +        }
    1.71 +    } else {
    1.72 +        texture->native = SDL_CreateTexture(renderer,
    1.73 +                                GetClosestSupportedFormat(renderer, format),
    1.74 +                                access, w, h);
    1.75 +        if (!texture->native) {
    1.76 +            SDL_DestroyTexture(texture);
    1.77 +            return NULL;
    1.78 +        }
    1.79 +
    1.80 +        if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
    1.81 +            texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
    1.82 +            if (!texture->yuv) {
    1.83 +                SDL_DestroyTexture(texture);
    1.84 +                return NULL;
    1.85 +            }
    1.86 +        } else if (access == SDL_TEXTUREACCESS_STREAMING) {
    1.87 +            /* The pitch is 4 byte aligned */
    1.88 +            texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
    1.89 +            texture->pixels = SDL_malloc(texture->pitch * h);
    1.90 +            if (!texture->pixels) {
    1.91 +                SDL_DestroyTexture(texture);
    1.92 +                return NULL;
    1.93 +            }
    1.94 +        }
    1.95      }
    1.96      return texture;
    1.97  }
    1.98 @@ -501,21 +559,6 @@
    1.99  }
   1.100  
   1.101  int
   1.102 -SDL_QueryTexturePixels(SDL_Texture * texture, void **pixels, int *pitch)
   1.103 -{
   1.104 -    SDL_Renderer *renderer;
   1.105 -
   1.106 -    CHECK_TEXTURE_MAGIC(texture, -1);
   1.107 -
   1.108 -    renderer = texture->renderer;
   1.109 -    if (!renderer->QueryTexturePixels) {
   1.110 -        SDL_Unsupported();
   1.111 -        return -1;
   1.112 -    }
   1.113 -    return renderer->QueryTexturePixels(renderer, texture, pixels, pitch);
   1.114 -}
   1.115 -
   1.116 -int
   1.117  SDL_SetTextureColorMod(SDL_Texture * texture, Uint8 r, Uint8 g, Uint8 b)
   1.118  {
   1.119      SDL_Renderer *renderer;
   1.120 @@ -531,7 +574,9 @@
   1.121      texture->r = r;
   1.122      texture->g = g;
   1.123      texture->b = b;
   1.124 -    if (renderer->SetTextureColorMod) {
   1.125 +    if (texture->native) {
   1.126 +        return SDL_SetTextureColorMod(texture->native, r, g, b);
   1.127 +    } else if (renderer->SetTextureColorMod) {
   1.128          return renderer->SetTextureColorMod(renderer, texture);
   1.129      } else {
   1.130          return 0;
   1.131 @@ -573,7 +618,9 @@
   1.132          texture->modMode &= ~SDL_TEXTUREMODULATE_ALPHA;
   1.133      }
   1.134      texture->a = alpha;
   1.135 -    if (renderer->SetTextureAlphaMod) {
   1.136 +    if (texture->native) {
   1.137 +        return SDL_SetTextureAlphaMod(texture->native, alpha);
   1.138 +    } else if (renderer->SetTextureAlphaMod) {
   1.139          return renderer->SetTextureAlphaMod(renderer, texture);
   1.140      } else {
   1.141          return 0;
   1.142 @@ -600,7 +647,9 @@
   1.143  
   1.144      renderer = texture->renderer;
   1.145      texture->blendMode = blendMode;
   1.146 -    if (renderer->SetTextureBlendMode) {
   1.147 +    if (texture->native) {
   1.148 +        return SDL_SetTextureBlendMode(texture, blendMode);
   1.149 +    } else if (renderer->SetTextureBlendMode) {
   1.150          return renderer->SetTextureBlendMode(renderer, texture);
   1.151      } else {
   1.152          return 0;
   1.153 @@ -618,6 +667,91 @@
   1.154      return 0;
   1.155  }
   1.156  
   1.157 +static int
   1.158 +SDL_UpdateTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
   1.159 +                     const void *pixels, int pitch)
   1.160 +{
   1.161 +    SDL_Texture *native = texture->native;
   1.162 +    SDL_Rect full_rect;
   1.163 +
   1.164 +    if (SDL_SW_UpdateYUVTexture(texture->yuv, rect, pixels, pitch) < 0) {
   1.165 +        return -1;
   1.166 +    }
   1.167 +
   1.168 +    full_rect.x = 0;
   1.169 +    full_rect.y = 0;
   1.170 +    full_rect.w = texture->w;
   1.171 +    full_rect.h = texture->h;
   1.172 +    rect = &full_rect;
   1.173 +
   1.174 +    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   1.175 +        /* We can lock the texture and copy to it */
   1.176 +        void *native_pixels;
   1.177 +        int native_pitch;
   1.178 +
   1.179 +        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
   1.180 +            return -1;
   1.181 +        }
   1.182 +        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
   1.183 +                            rect->w, rect->h, native_pixels, native_pitch);
   1.184 +        SDL_UnlockTexture(native);
   1.185 +    } else {
   1.186 +        /* Use a temporary buffer for updating */
   1.187 +        void *temp_pixels;
   1.188 +        int temp_pitch;
   1.189 +
   1.190 +        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
   1.191 +        temp_pixels = SDL_malloc(rect->h * temp_pitch);
   1.192 +        if (!temp_pixels) {
   1.193 +            SDL_OutOfMemory();
   1.194 +            return -1;
   1.195 +        }
   1.196 +        SDL_SW_CopyYUVToRGB(texture->yuv, rect, native->format,
   1.197 +                            rect->w, rect->h, temp_pixels, temp_pitch);
   1.198 +        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
   1.199 +        SDL_free(temp_pixels);
   1.200 +    }
   1.201 +    return 0;
   1.202 +}
   1.203 +
   1.204 +static int
   1.205 +SDL_UpdateTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
   1.206 +                        const void *pixels, int pitch)
   1.207 +{
   1.208 +    SDL_Texture *native = texture->native;
   1.209 +
   1.210 +    if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
   1.211 +        /* We can lock the texture and copy to it */
   1.212 +        void *native_pixels;
   1.213 +        int native_pitch;
   1.214 +
   1.215 +        if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
   1.216 +            return -1;
   1.217 +        }
   1.218 +        SDL_ConvertPixels(rect->w, rect->h,
   1.219 +                          texture->format, pixels, pitch,
   1.220 +                          native->format, native_pixels, native_pitch);
   1.221 +        SDL_UnlockTexture(native);
   1.222 +    } else {
   1.223 +        /* Use a temporary buffer for updating */
   1.224 +        void *temp_pixels;
   1.225 +        int temp_pitch;
   1.226 +
   1.227 +        temp_pitch = (((rect->w * SDL_BYTESPERPIXEL(native->format)) + 3) & ~3);
   1.228 +        temp_pixels = SDL_malloc(rect->h * temp_pitch);
   1.229 +        if (!temp_pixels) {
   1.230 +            SDL_OutOfMemory();
   1.231 +            return -1;
   1.232 +        }
   1.233 +        SDL_ConvertPixels(rect->w, rect->h,
   1.234 +                          texture->format, pixels, pitch,
   1.235 +                          native->format, temp_pixels, temp_pitch);
   1.236 +        SDL_UpdateTexture(native, rect, temp_pixels, temp_pitch);
   1.237 +        SDL_free(temp_pixels);
   1.238 +    }
   1.239 +    return 0;
   1.240 +}
   1.241 +
   1.242  int
   1.243  SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,
   1.244                    const void *pixels, int pitch)
   1.245 @@ -627,11 +761,6 @@
   1.246  
   1.247      CHECK_TEXTURE_MAGIC(texture, -1);
   1.248  
   1.249 -    renderer = texture->renderer;
   1.250 -    if (!renderer->UpdateTexture) {
   1.251 -        SDL_Unsupported();
   1.252 -        return -1;
   1.253 -    }
   1.254      if (!rect) {
   1.255          full_rect.x = 0;
   1.256          full_rect.y = 0;
   1.257 @@ -639,11 +768,38 @@
   1.258          full_rect.h = texture->h;
   1.259          rect = &full_rect;
   1.260      }
   1.261 -    return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
   1.262 +
   1.263 +    if (texture->yuv) {
   1.264 +        return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);
   1.265 +    } else if (texture->native) {
   1.266 +        return SDL_UpdateTextureNative(texture, rect, pixels, pitch);
   1.267 +    } else {
   1.268 +        renderer = texture->renderer;
   1.269 +        return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);
   1.270 +    }
   1.271 +}
   1.272 +
   1.273 +static int
   1.274 +SDL_LockTextureYUV(SDL_Texture * texture, const SDL_Rect * rect,
   1.275 +                   void **pixels, int *pitch)
   1.276 +{
   1.277 +    return SDL_SW_LockYUVTexture(texture->yuv, rect, pixels, pitch);
   1.278 +}
   1.279 +
   1.280 +static int
   1.281 +SDL_LockTextureNative(SDL_Texture * texture, const SDL_Rect * rect,
   1.282 +                      void **pixels, int *pitch)
   1.283 +{
   1.284 +    texture->locked_rect = *rect;
   1.285 +    *pixels = (void *) ((Uint8 *) texture->pixels +
   1.286 +                        rect->y * texture->pitch +
   1.287 +                        rect->x * SDL_BYTESPERPIXEL(texture->format));
   1.288 +    *pitch = texture->pitch;
   1.289 +    return 0;
   1.290  }
   1.291  
   1.292  int
   1.293 -SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect, int markDirty,
   1.294 +SDL_LockTexture(SDL_Texture * texture, const SDL_Rect * rect,
   1.295                  void **pixels, int *pitch)
   1.296  {
   1.297      SDL_Renderer *renderer;
   1.298 @@ -655,11 +811,7 @@
   1.299          SDL_SetError("SDL_LockTexture(): texture must be streaming");
   1.300          return -1;
   1.301      }
   1.302 -    renderer = texture->renderer;
   1.303 -    if (!renderer->LockTexture) {
   1.304 -        SDL_Unsupported();
   1.305 -        return -1;
   1.306 -    }
   1.307 +
   1.308      if (!rect) {
   1.309          full_rect.x = 0;
   1.310          full_rect.y = 0;
   1.311 @@ -667,8 +819,57 @@
   1.312          full_rect.h = texture->h;
   1.313          rect = &full_rect;
   1.314      }
   1.315 -    return renderer->LockTexture(renderer, texture, rect, markDirty, pixels,
   1.316 -                                 pitch);
   1.317 +
   1.318 +    if (texture->yuv) {
   1.319 +        return SDL_LockTextureYUV(texture, rect, pixels, pitch);
   1.320 +    } else if (texture->native) {
   1.321 +        return SDL_LockTextureNative(texture, rect, pixels, pitch);
   1.322 +    } else {
   1.323 +        renderer = texture->renderer;
   1.324 +        return renderer->LockTexture(renderer, texture, rect, pixels, pitch);
   1.325 +    }
   1.326 +}
   1.327 +
   1.328 +static void
   1.329 +SDL_UnlockTextureYUV(SDL_Texture * texture)
   1.330 +{
   1.331 +    SDL_Texture *native = texture->native;
   1.332 +    void *native_pixels;
   1.333 +    int native_pitch;
   1.334 +    SDL_Rect rect;
   1.335 +
   1.336 +    rect.x = 0;
   1.337 +    rect.y = 0;
   1.338 +    rect.w = texture->w;
   1.339 +    rect.h = texture->h;
   1.340 +
   1.341 +    if (SDL_LockTexture(native, &rect, &native_pixels, &native_pitch) < 0) {
   1.342 +        return;
   1.343 +    }
   1.344 +    SDL_SW_CopyYUVToRGB(texture->yuv, &rect, native->format,
   1.345 +                        rect.w, rect.h, native_pixels, native_pitch);
   1.346 +    SDL_UnlockTexture(native);
   1.347 +}
   1.348 +
   1.349 +void
   1.350 +SDL_UnlockTextureNative(SDL_Texture * texture)
   1.351 +{
   1.352 +    SDL_Texture *native = texture->native;
   1.353 +    void *native_pixels;
   1.354 +    int native_pitch;
   1.355 +    const SDL_Rect *rect = &texture->locked_rect;
   1.356 +    const void* pixels = (void *) ((Uint8 *) texture->pixels +
   1.357 +                        rect->y * texture->pitch +
   1.358 +                        rect->x * SDL_BYTESPERPIXEL(texture->format));
   1.359 +    int pitch = texture->pitch;
   1.360 +
   1.361 +    if (SDL_LockTexture(native, rect, &native_pixels, &native_pitch) < 0) {
   1.362 +        return;
   1.363 +    }
   1.364 +    SDL_ConvertPixels(rect->w, rect->h,
   1.365 +                      texture->format, pixels, pitch,
   1.366 +                      native->format, native_pixels, native_pitch);
   1.367 +    SDL_UnlockTexture(native);
   1.368  }
   1.369  
   1.370  void
   1.371 @@ -681,29 +882,14 @@
   1.372      if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
   1.373          return;
   1.374      }
   1.375 -    renderer = texture->renderer;
   1.376 -    if (!renderer->UnlockTexture) {
   1.377 -        return;
   1.378 +    if (texture->yuv) {
   1.379 +        SDL_UnlockTextureYUV(texture);
   1.380 +    } else if (texture->native) {
   1.381 +        SDL_UnlockTextureNative(texture);
   1.382 +    } else {
   1.383 +        renderer = texture->renderer;
   1.384 +        renderer->UnlockTexture(renderer, texture);
   1.385      }
   1.386 -    renderer->UnlockTexture(renderer, texture);
   1.387 -}
   1.388 -
   1.389 -void
   1.390 -SDL_DirtyTexture(SDL_Texture * texture, int numrects,
   1.391 -                 const SDL_Rect * rects)
   1.392 -{
   1.393 -    SDL_Renderer *renderer;
   1.394 -
   1.395 -    CHECK_TEXTURE_MAGIC(texture, );
   1.396 -
   1.397 -    if (texture->access != SDL_TEXTUREACCESS_STREAMING) {
   1.398 -        return;
   1.399 -    }
   1.400 -    renderer = texture->renderer;
   1.401 -    if (!renderer->DirtyTexture) {
   1.402 -        return;
   1.403 -    }
   1.404 -    renderer->DirtyTexture(renderer, texture, numrects, rects);
   1.405  }
   1.406  
   1.407  int
   1.408 @@ -979,6 +1165,10 @@
   1.409          }
   1.410      }
   1.411  
   1.412 +    if (texture->native) {
   1.413 +        texture = texture->native;
   1.414 +    }
   1.415 +
   1.416      return renderer->RenderCopy(renderer, texture, &real_srcrect,
   1.417                                  &real_dstrect);
   1.418  }
   1.419 @@ -1087,6 +1277,16 @@
   1.420          renderer->textures = texture->next;
   1.421      }
   1.422  
   1.423 +    if (texture->native) {
   1.424 +        SDL_DestroyTexture(texture->native);
   1.425 +    }
   1.426 +    if (texture->yuv) {
   1.427 +        SDL_SW_DestroyYUVTexture(texture->yuv);
   1.428 +    }
   1.429 +    if (texture->pixels) {
   1.430 +        SDL_free(texture->pixels);
   1.431 +    }
   1.432 +
   1.433      renderer->DestroyTexture(renderer, texture);
   1.434      SDL_free(texture);
   1.435  }