From 10b8a741a27b1b1497543c6e17b036b23b7cb73e Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 11 Aug 2007 20:54:31 +0000 Subject: [PATCH] Emphasized the separation between SDL_Surface and SDL_Texture - SDL_Surface is a system memory representation of pixel data - SDL_Texture is a video memory representation of pixel data The concept of SDL_Surface with SDL_HWSURFACE is no longer used. Separated SDL_Texture types by usage rather than memory type - SDL_TEXTUREACCESS_STATIC is for rarely changed pixel data, can be placed in video memory. - SDL_TEXTUREACCESS_STREAMING is for frequently changing pixel data, usually placed in system memory or AGP memory. Optimized the SDL_compat usage of the OpenGL renderer by only using one copy of the framebuffer instead of two. --- include/SDL_compat.h | 3 +- include/SDL_video.h | 30 +++--- src/SDL_compat.c | 90 +++++++++++------ src/video/SDL_RLEaccel.c | 7 +- src/video/SDL_renderer_gl.c | 34 +++++-- src/video/SDL_renderer_sw.c | 2 +- src/video/SDL_surface.c | 139 +------------------------- src/video/SDL_video.c | 171 ++++++++++++++++++-------------- src/video/win32/SDL_d3drender.c | 19 +--- src/video/win32/SDL_gdirender.c | 2 +- test/testsprite2.c | 3 +- 11 files changed, 206 insertions(+), 294 deletions(-) diff --git a/include/SDL_compat.h b/include/SDL_compat.h index bac3ca225..3d07520aa 100644 --- a/include/SDL_compat.h +++ b/include/SDL_compat.h @@ -36,7 +36,7 @@ extern "C" { /* *INDENT-ON* */ #endif -#define SDL_SWSURFACE 0x00000000 +#define SDL_SWSURFACE 0x00000000 /* Not used */ #define SDL_ANYFORMAT 0x00100000 #define SDL_HWPALETTE 0x00200000 #define SDL_DOUBLEBUF 0x00400000 @@ -44,6 +44,7 @@ extern "C" { #define SDL_RESIZABLE 0x01000000 #define SDL_NOFRAME 0x02000000 #define SDL_OPENGL 0x04000000 +#define SDL_HWSURFACE 0x08000001 /* Not used */ #define SDL_ASYNCBLIT 0x08000000 /* Not used */ #define SDL_HWACCEL 0x08000000 /* Not used */ diff --git a/include/SDL_video.h b/include/SDL_video.h index c668b9a69..f05a5f220 100644 --- a/include/SDL_video.h +++ b/include/SDL_video.h @@ -204,8 +204,8 @@ typedef struct SDL_RendererInfo */ typedef enum { - SDL_TEXTUREACCESS_LOCAL, /**< Lockable system memory */ - SDL_TEXTUREACCESS_REMOTE /**< Unlockable video memory */ + SDL_TEXTUREACCESS_STATIC, /**< Changes rarely, not lockable */ + SDL_TEXTUREACCESS_STREAMING /**< Changes frequently, lockable */ } SDL_TextureAccess; /** @@ -264,15 +264,14 @@ typedef void *SDL_GLContext; /* These are the currently supported flags for the SDL_surface */ /* Used internally (read-only) */ -#define SDL_HWSURFACE 0x00000001 /* Surface represents a texture */ -#define SDL_PREALLOC 0x00000002 /* Surface uses preallocated memory */ +#define SDL_PREALLOC 0x00000001 /* Surface uses preallocated memory */ #define SDL_SRCALPHA 0x00000004 /* Blit uses source alpha blending */ #define SDL_SRCCOLORKEY 0x00000008 /* Blit uses a source color key */ #define SDL_RLEACCELOK 0x00000010 /* Private flag */ #define SDL_RLEACCEL 0x00000020 /* Surface is RLE encoded */ /* Evaluates to true if the surface needs to be locked before access */ -#define SDL_MUSTLOCK(S) (((S)->flags & (SDL_HWSURFACE|SDL_RLEACCEL)) != 0) +#define SDL_MUSTLOCK(S) (((S)->flags & SDL_RLEACCEL) != 0) /* This structure should be treated as read-only, except for 'pixels', which, if not NULL, contains the raw pixel data for the surface. @@ -288,9 +287,6 @@ typedef struct SDL_Surface /* Application data associated with the surfade */ void *userdata; /* Read-write */ - /* texture associated with the surface, if any */ - SDL_TextureID textureID; /* Read-only */ - /* information needed for surfaces requiring locks */ int locked; /* Read-only */ void *lock_data; /* Read-only */ @@ -927,12 +923,11 @@ extern DECLSPEC SDL_TextureID SDLCALL SDL_CreateTexture(Uint32 format, int h); /** - * \fn SDL_TextureID SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface *surface) + * \fn SDL_TextureID SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface *surface) * * \brief Create a texture from an existing surface. * * \param format The format of the texture, or 0 to pick an appropriate format - * \param access One of the enumerated values in SDL_TextureAccess * \param surface The surface containing pixel data used to fill the texture * * \return The created texture is returned, or 0 if no rendering context was active, the format was unsupported, or the surface width or height were out of range. @@ -944,7 +939,6 @@ extern DECLSPEC SDL_TextureID SDLCALL SDL_CreateTexture(Uint32 format, */ extern DECLSPEC SDL_TextureID SDLCALL SDL_CreateTextureFromSurface(Uint32 format, - int access, SDL_Surface * surface); @@ -970,7 +964,7 @@ extern DECLSPEC int SDLCALL SDL_QueryTexture(SDL_TextureID textureID, * * \brief Query the pixels of a texture, if the texture does not need to be locked for pixel access. * - * \param texture A texture to be queried, which was created with SDL_TEXTUREACCESS_LOCAL + * \param texture A texture to be queried, which was created with SDL_TEXTUREACCESS_STREAMING * \param pixels A pointer filled with a pointer to the pixels for the texture * \param pitch A pointer filled in with the pitch of the pixel data * @@ -1155,7 +1149,7 @@ extern DECLSPEC int SDLCALL SDL_GetTextureScaleMode(SDL_TextureID textureID, * * \return 0 on success, or -1 if the texture is not valid * - * \note This is a very slow function for textures not created with SDL_TEXTUREACCESS_LOCAL. + * \note This is a fairly slow function. */ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_TextureID textureID, const SDL_Rect * rect, @@ -1166,13 +1160,13 @@ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_TextureID textureID, * * \brief Lock a portion of the texture for pixel access. * - * \param texture The texture to lock for access, which must have been created with SDL_TEXTUREACCESS_LOCAL. + * \param textureID The texture to lock for access, which was created with SDL_TEXTUREACCESS_STREAMING. * \param rect A pointer to the rectangle to lock for access. If the rect is NULL, the entire texture will be locked. * \param markDirty If this is nonzero, the locked area will be marked dirty when the texture is unlocked. * \param pixels This is filled in with a pointer to the locked pixels, appropriately offset by the locked area. * \param pitch This is filled in with the pitch of the locked pixels. * - * \return 0 on success, or -1 if the texture is not valid or was created with SDL_TEXTUREACCESS_REMOTe + * \return 0 on success, or -1 if the texture is not valid or was created with SDL_TEXTUREACCESS_STATIC * * \sa SDL_DirtyTexture() * \sa SDL_UnlockTexture() @@ -1197,7 +1191,9 @@ extern DECLSPEC void SDLCALL SDL_UnlockTexture(SDL_TextureID textureID); * * \brief Mark the specified rectangles of the texture as dirty. * - * \note The texture must have been created with SDL_TEXTUREACCESS_LOCAL. + * \param textureID The texture to mark dirty, which was created with SDL_TEXTUREACCESS_STREAMING. + * \param numrects The number of rectangles pointed to by rects. + * \param rects The pointer to an array of dirty rectangles. * * \sa SDL_LockTexture() * \sa SDL_UnlockTexture() @@ -1347,8 +1343,6 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); -extern DECLSPEC SDL_Surface *SDLCALL -SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID); extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface); /** diff --git a/src/SDL_compat.c b/src/SDL_compat.c index 3957a88a4..24251fd91 100644 --- a/src/SDL_compat.c +++ b/src/SDL_compat.c @@ -328,6 +328,38 @@ GetEnvironmentWindowPosition(int w, int h, int *x, int *y) } } +static SDL_Surface * +CreateVideoSurface(SDL_TextureID textureID) +{ + SDL_Surface *surface; + Uint32 format; + int w, h; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + void *pixels; + int pitch; + + if (SDL_QueryTexture(textureID, &format, NULL, &w, &h) < 0) { + return NULL; + } + + if (!SDL_PixelFormatEnumToMasks + (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { + SDL_SetError("Unknown texture format"); + return NULL; + } + + if (SDL_QueryTexturePixels(textureID, &pixels, &pitch) == 0) { + surface = + SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask, Gmask, + Bmask, Amask); + } else { + surface = + SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); + } + return surface; +} + SDL_Surface * SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) { @@ -483,23 +515,23 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD) < 0) { return NULL; } - SDL_GetRenderDriverInfo(-1, &SDL_VideoRendererInfo); + SDL_GetRendererInfo(&SDL_VideoRendererInfo); /* Create a texture for the screen surface */ SDL_VideoTexture = - SDL_CreateTexture(desired_format, SDL_TEXTUREACCESS_LOCAL, width, + SDL_CreateTexture(desired_format, SDL_TEXTUREACCESS_STREAMING, width, height); if (!SDL_VideoTexture) { SDL_VideoTexture = - SDL_CreateTexture(SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_LOCAL, - width, height); + SDL_CreateTexture(SDL_PIXELFORMAT_RGB888, + SDL_TEXTUREACCESS_STREAMING, width, height); } if (!SDL_VideoTexture) { return NULL; } /* Create the screen surface */ - SDL_VideoSurface = SDL_CreateRGBSurfaceFromTexture(SDL_VideoTexture); + SDL_VideoSurface = CreateVideoSurface(SDL_VideoTexture); if (!SDL_VideoSurface) { return NULL; } @@ -518,23 +550,10 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) } /* Create a shadow surface if necessary */ - if (((bpp != SDL_VideoSurface->format->BitsPerPixel) - && !(flags & SDL_ANYFORMAT)) - || ((SDL_VideoSurface->flags & SDL_HWSURFACE) - && !(flags & SDL_HWSURFACE))) { - if ((bpp == SDL_VideoSurface->format->BitsPerPixel) - || (flags & SDL_ANYFORMAT)) { - SDL_ShadowSurface = - SDL_CreateRGBSurface(0, width, height, - SDL_VideoSurface->format->BitsPerPixel, - SDL_VideoSurface->format->Rmask, - SDL_VideoSurface->format->Gmask, - SDL_VideoSurface->format->Bmask, - SDL_VideoSurface->format->Amask); - } else { - SDL_ShadowSurface = - SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0); - } + if ((bpp != SDL_VideoSurface->format->BitsPerPixel) + && !(flags & SDL_ANYFORMAT)) { + SDL_ShadowSurface = + SDL_CreateRGBSurface(0, width, height, bpp, 0, 0, 0, 0); if (!SDL_ShadowSurface) { return NULL; } @@ -638,8 +657,7 @@ SDL_DisplayFormatAlpha(SDL_Surface * surface) break; } format = SDL_AllocFormat(32, rmask, gmask, bmask, amask); - flags = SDL_PublicSurface->flags & SDL_HWSURFACE; - flags |= surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + flags = surface->flags & (SDL_SRCALPHA | SDL_RLEACCELOK); converted = SDL_ConvertSurface(surface, format, flags); SDL_FreeFormat(format); return converted; @@ -681,6 +699,22 @@ SDL_UpdateRects(SDL_Surface * screen, int numrects, SDL_Rect * rects) screen = SDL_VideoSurface; } if (screen == SDL_VideoSurface) { + if (screen->flags & SDL_PREALLOC) { + /* The surface memory is maintained by the renderer */ + SDL_DirtyTexture(SDL_VideoTexture, numrects, rects); + } else { + /* The surface memory needs to be copied to texture */ + void *pixels; + int pitch = screen->pitch; + int psize = screen->format->BytesPerPixel; + for (i = 0; i < numrects; ++i) { + const SDL_Rect *rect = &rects[i]; + void *pixels = + (Uint8 *) screen->pixels + rect->y * pitch + + rect->x * psize; + SDL_UpdateTexture(SDL_VideoTexture, rect, pixels, pitch); + } + } if (SDL_VideoRendererInfo.flags & SDL_RENDERER_PRESENTCOPY) { for (i = 0; i < numrects; ++i) { SDL_RenderCopy(SDL_VideoTexture, &rects[i], &rects[i]); @@ -1174,8 +1208,7 @@ SDL_DrawCursor(SDL_Surface * screen) if (SDL_MUSTLOCK(screen)) { SDL_UnlockSurface(screen); } - if ((screen->flags & SDL_SCREEN_SURFACE) && - !(screen->flags & SDL_HWSURFACE)) { + if (screen->flags & SDL_SCREEN_SURFACE) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_Window *window; SDL_Rect area; @@ -1263,8 +1296,7 @@ SDL_EraseCursor(SDL_Surface * screen) if (SDL_MUSTLOCK(screen)) { SDL_UnlockSurface(screen); } - if ((screen->flags & SDL_SCREEN_SURFACE) && - !(screen->flags & SDL_HWSURFACE)) { + if (screen->flags & SDL_SCREEN_SURFACE) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); SDL_Window *window; SDL_Rect area; @@ -1385,7 +1417,7 @@ SDL_CreateYUVOverlay(int w, int h, Uint32 format, SDL_Surface * display) } overlay->hwdata->textureID = - SDL_CreateTexture(texture_format, SDL_TEXTUREACCESS_LOCAL, w, h); + SDL_CreateTexture(texture_format, SDL_TEXTUREACCESS_STREAMING, w, h); if (!overlay->hwdata->textureID) { SDL_FreeYUVOverlay(overlay); return NULL; diff --git a/src/video/SDL_RLEaccel.c b/src/video/SDL_RLEaccel.c index 3101dcf18..7a76d679d 100644 --- a/src/video/SDL_RLEaccel.c +++ b/src/video/SDL_RLEaccel.c @@ -1618,7 +1618,7 @@ RLEAlphaSurface(SDL_Surface * surface) #undef ADD_TRANSL_COUNTS /* Now that we have it encoded, release the original pixels */ - if (!(surface->flags & SDL_PREALLOC) && !(surface->flags & SDL_HWSURFACE)) { + if (!(surface->flags & SDL_PREALLOC)) { SDL_free(surface->pixels); surface->pixels = NULL; } @@ -1783,7 +1783,7 @@ RLEColorkeySurface(SDL_Surface * surface) #undef ADD_COUNTS /* Now that we have it encoded, release the original pixels */ - if (!(surface->flags & SDL_PREALLOC) && !(surface->flags & SDL_HWSURFACE)) { + if (!(surface->flags & SDL_PREALLOC)) { SDL_free(surface->pixels); surface->pixels = NULL; } @@ -1934,8 +1934,7 @@ SDL_UnRLESurface(SDL_Surface * surface, int recode) if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { surface->flags &= ~SDL_RLEACCEL; - if (recode && !(surface->flags & SDL_PREALLOC) - && !(surface->flags & SDL_HWSURFACE)) { + if (recode && !(surface->flags & SDL_PREALLOC)) { if ((surface->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) { SDL_Rect full; unsigned alpha_flag; diff --git a/src/video/SDL_renderer_gl.c b/src/video/SDL_renderer_gl.c index 0ecd59797..5da43bbf4 100644 --- a/src/video/SDL_renderer_gl.c +++ b/src/video/SDL_renderer_gl.c @@ -38,6 +38,9 @@ static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags); static int GL_ActivateRenderer(SDL_Renderer * renderer); static int GL_DisplayModeChanged(SDL_Renderer * renderer); static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static int GL_QueryTexturePixels(SDL_Renderer * renderer, + SDL_Texture * texture, void **pixels, + int *pitch); static int GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Color * colors, int firstcolor, @@ -245,6 +248,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) renderer->ActivateRenderer = GL_ActivateRenderer; renderer->DisplayModeChanged = GL_DisplayModeChanged; renderer->CreateTexture = GL_CreateTexture; + renderer->QueryTexturePixels = GL_QueryTexturePixels; renderer->SetTexturePalette = GL_SetTexturePalette; renderer->GetTexturePalette = GL_GetTexturePalette; renderer->SetTextureColorMod = GL_SetTextureColorMod; @@ -492,6 +496,16 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_memset(data->palette, 0xFF, 3 * 256 * sizeof(Uint8)); } + if (texture->access == SDL_TEXTUREACCESS_STREAMING) { + data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); + data->pixels = SDL_malloc(texture->h * data->pitch); + if (!data->pixels) { + SDL_OutOfMemory(); + SDL_free(data); + return -1; + } + } + texture->driverdata = data; renderdata->glGetError(); @@ -522,6 +536,17 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) return 0; } +static int +GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture, + void **pixels, int *pitch) +{ + GL_TextureData *data = (GL_TextureData *) texture->driverdata; + + *pixels = data->pixels; + *pitch = data->pitch; + return 0; +} + static int GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Color * colors, int firstcolor, int ncolors) @@ -661,15 +686,6 @@ GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, { GL_TextureData *data = (GL_TextureData *) texture->driverdata; - if (!data->pixels) { - data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); - data->pixels = SDL_malloc(texture->h * data->pitch); - if (!data->pixels) { - SDL_OutOfMemory(); - return -1; - } - } - if (markDirty) { SDL_AddDirtyRect(&data->dirty, rect); } diff --git a/src/video/SDL_renderer_sw.c b/src/video/SDL_renderer_sw.c index 655136723..59570e4df 100644 --- a/src/video/SDL_renderer_sw.c +++ b/src/video/SDL_renderer_sw.c @@ -125,7 +125,7 @@ CreateTexture(SDL_Renderer * renderer, Uint32 format, int w, int h) } texture->format = format; - texture->access = SDL_TEXTUREACCESS_LOCAL; + texture->access = SDL_TEXTUREACCESS_STREAMING; texture->w = w; texture->h = h; texture->renderer = renderer; diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index afb8178e1..a077974df 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -170,62 +170,11 @@ SDL_CreateRGBSurfaceFrom(void *pixels, return surface; } -SDL_Surface * -SDL_CreateRGBSurfaceFromTexture(SDL_TextureID textureID) -{ - SDL_Surface *surface; - Uint32 format; - int w, h; - int bpp; - Uint32 Rmask, Gmask, Bmask, Amask; - void *pixels; - int pitch; - - if (SDL_QueryTexture(textureID, &format, NULL, &w, &h) < 0) { - return NULL; - } - - if (!SDL_PixelFormatEnumToMasks - (format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { - SDL_SetError("Unknown texture format"); - return NULL; - } - - if (SDL_QueryTexturePixels(textureID, &pixels, &pitch) == 0) { - surface = - SDL_CreateRGBSurfaceFrom(pixels, w, h, bpp, pitch, Rmask, Gmask, - Bmask, Amask); - } else { - surface = - SDL_CreateRGBSurface(0, 0, 0, bpp, Rmask, Gmask, Bmask, Amask); - if (surface) { - surface->flags |= SDL_HWSURFACE; - surface->w = w; - surface->h = h; - surface->pitch = SDL_CalculatePitch(surface); - SDL_SetClipRect(surface, NULL); - } - } - if (surface) { - surface->textureID = textureID; - } - - return surface; -} - static int SDL_SurfacePaletteChanged(void *userdata, SDL_Palette * palette) { SDL_Surface *surface = (SDL_Surface *) userdata; - if (surface->textureID) { - if (SDL_SetTexturePalette - (surface->textureID, palette->colors, 0, palette->ncolors) < 0) { - SDL_GetTexturePalette(surface->textureID, palette->colors, 0, - palette->ncolors); - return -1; - } - } SDL_FormatChanged(surface); return 0; @@ -627,74 +576,9 @@ SDL_FillRect(SDL_Surface * dst, SDL_Rect * dstrect, Uint32 color) row += dst->pitch; } } else { -#ifdef __powerpc__ - /* - * SDL_memset() on PPC (both glibc and codewarrior) uses - * the dcbz (Data Cache Block Zero) instruction, which - * causes an alignment exception if the destination is - * uncachable, so only use it on software surfaces - */ - if (dst->flags & SDL_HWSURFACE) { - if (dstrect->w >= 8) { - /* - * 64-bit stores are probably most - * efficient to uncached video memory - */ - double fill; - SDL_memset(&fill, color, (sizeof fill)); - for (y = dstrect->h; y; y--) { - Uint8 *d = row; - unsigned n = x; - unsigned nn; - Uint8 c = color; - double f = fill; - while ((unsigned long) d & (sizeof(double) - 1)) { - *d++ = c; - n--; - } - nn = n / (sizeof(double) * 4); - while (nn) { - ((double *) d)[0] = f; - ((double *) d)[1] = f; - ((double *) d)[2] = f; - ((double *) d)[3] = f; - d += 4 * sizeof(double); - nn--; - } - n &= ~(sizeof(double) * 4 - 1); - nn = n / sizeof(double); - while (nn) { - *(double *) d = f; - d += sizeof(double); - nn--; - } - n &= ~(sizeof(double) - 1); - while (n) { - *d++ = c; - n--; - } - row += dst->pitch; - } - } else { - /* narrow boxes */ - for (y = dstrect->h; y; y--) { - Uint8 *d = row; - Uint8 c = color; - int n = x; - while (n) { - *d++ = c; - n--; - } - row += dst->pitch; - } - } - } else -#endif /* __powerpc__ */ - { - for (y = dstrect->h; y; y--) { - SDL_memset(row, color, x); - row += dst->pitch; - } + for (y = dstrect->h; y; y--) { + SDL_memset(row, color, x); + row += dst->pitch; } } } else { @@ -753,13 +637,6 @@ SDL_LockSurface(SDL_Surface * surface) { if (!surface->locked) { /* Perform the lock */ - if (surface->flags & SDL_HWSURFACE) { - if (SDL_LockTexture - (surface->textureID, NULL, 1, &surface->pixels, - &surface->pitch) < 0) { - return (-1); - } - } if (surface->flags & SDL_RLEACCEL) { SDL_UnRLESurface(surface, 1); surface->flags |= SDL_RLEACCEL; /* save accel'd state */ @@ -784,11 +661,6 @@ SDL_UnlockSurface(SDL_Surface * surface) return; } - /* Unlock hardware or accelerated surfaces */ - if (surface->flags & SDL_HWSURFACE) { - SDL_UnlockTexture(surface->textureID); - } - /* Update RLE encoded surface with new data */ if ((surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL) { surface->flags &= ~SDL_RLEACCEL; /* stop lying */ @@ -928,11 +800,6 @@ SDL_FreeSurface(SDL_Surface * surface) SDL_FreeBlitMap(surface->map); surface->map = NULL; } - /* Should we destroy the texture too? - if (surface->textureID) { - SDL_DestroyTexture(surface->textureID); - } - */ if (surface->pixels && ((surface->flags & SDL_PREALLOC) != SDL_PREALLOC)) { SDL_free(surface->pixels); } diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index e3373aa3d..9801572a1 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1532,14 +1532,11 @@ SDL_CreateTexture(Uint32 format, int access, int w, int h) } SDL_TextureID -SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) +SDL_CreateTextureFromSurface(Uint32 format, SDL_Surface * surface) { SDL_TextureID textureID; Uint32 surface_flags = surface->flags; SDL_PixelFormat *fmt = surface->format; - Uint8 alpha; - SDL_Rect bounds; - SDL_Surface dst; int bpp; Uint32 Rmask, Gmask, Bmask, Amask; @@ -1576,23 +1573,41 @@ SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) } } - textureID = SDL_CreateTexture(format, access, surface->w, surface->h); + textureID = + SDL_CreateTexture(format, SDL_TEXTUREACCESS_STATIC, surface->w, + surface->h); if (!textureID) { return 0; } - /* Set up a destination surface for the texture update */ - SDL_zero(dst); - dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); - if (!dst.format) { - SDL_DestroyTexture(textureID); - return 0; - } - dst.w = surface->w; - dst.h = surface->h; - if (SDL_LockTexture(textureID, NULL, 1, &dst.pixels, &dst.pitch) == 0) { - dst.flags |= SDL_PREALLOC; + if (bpp == fmt->BitsPerPixel && Rmask == fmt->Rmask && Gmask == fmt->Gmask + && Bmask == fmt->Bmask && Amask == fmt->Amask) { + if (SDL_MUSTLOCK(surface)) { + if (SDL_LockSurface(surface) < 0) { + SDL_DestroyTexture(textureID); + return 0; + } + SDL_UpdateTexture(textureID, NULL, surface->pixels, + surface->pitch); + SDL_UnlockSurface(surface); + } else { + SDL_UpdateTexture(textureID, NULL, surface->pixels, + surface->pitch); + } } else { + Uint8 alpha; + SDL_Rect bounds; + SDL_Surface dst; + + /* Set up a destination surface for the texture update */ + SDL_zero(dst); + dst.format = SDL_AllocFormat(bpp, Rmask, Gmask, Bmask, Amask); + if (!dst.format) { + SDL_DestroyTexture(textureID); + return 0; + } + dst.w = surface->w; + dst.h = surface->h; dst.pitch = SDL_CalculatePitch(&dst); dst.pixels = SDL_malloc(dst.h * dst.pitch); if (!dst.pixels) { @@ -1601,76 +1616,72 @@ SDL_CreateTextureFromSurface(Uint32 format, int access, SDL_Surface * surface) SDL_OutOfMemory(); return 0; } - } - /* Copy the palette if any */ - if (SDL_ISPIXELFORMAT_INDEXED(format)) { - if (fmt->palette) { - SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, - fmt->palette->ncolors); - SDL_SetSurfacePalette(&dst, fmt->palette); - } else { - dst.format->palette = - SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format))); - if (!dst.format->palette) { - SDL_DestroyTexture(textureID); - SDL_FreeFormat(dst.format); - return 0; + /* Copy the palette if any */ + if (SDL_ISPIXELFORMAT_INDEXED(format)) { + if (fmt->palette) { + SDL_SetTexturePalette(textureID, fmt->palette->colors, 0, + fmt->palette->ncolors); + SDL_SetSurfacePalette(&dst, fmt->palette); + } else { + dst.format->palette = + SDL_AllocPalette((1 << SDL_BITSPERPIXEL(format))); + if (!dst.format->palette) { + SDL_DestroyTexture(textureID); + SDL_FreeFormat(dst.format); + return 0; + } + SDL_DitherColors(dst.format->palette->colors, + SDL_BITSPERPIXEL(format)); } - SDL_DitherColors(dst.format->palette->colors, - SDL_BITSPERPIXEL(format)); } - } - /* Make the texture transparent if the surface has colorkey */ - if (surface_flags & SDL_SRCCOLORKEY) { - int row; - int length = dst.w * dst.format->BytesPerPixel; - Uint8 *p = (Uint8 *) dst.pixels; - for (row = 0; row < dst.h; ++row) { - SDL_memset(p, 0, length); - p += dst.pitch; + /* Make the texture transparent if the surface has colorkey */ + if (surface_flags & SDL_SRCCOLORKEY) { + int row; + int length = dst.w * dst.format->BytesPerPixel; + Uint8 *p = (Uint8 *) dst.pixels; + for (row = 0; row < dst.h; ++row) { + SDL_memset(p, 0, length); + p += dst.pitch; + } } - } - /* Copy over the alpha channel */ - if (surface_flags & SDL_SRCALPHA) { - if (fmt->Amask) { - surface->flags &= ~SDL_SRCALPHA; - } else { - /* FIXME: Need to make sure the texture has an alpha channel - * and copy 'alpha' into the texture alpha channel. - */ - alpha = surface->format->alpha; - SDL_SetAlpha(surface, 0, 0); - } - } - - /* Copy over the image data */ - bounds.x = 0; - bounds.y = 0; - bounds.w = surface->w; - bounds.h = surface->h; - SDL_LowerBlit(surface, &bounds, &dst, &bounds); - - /* Clean up the original surface */ - if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { - Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); - if (fmt->Amask) { - surface->flags |= SDL_SRCALPHA; - } else { - SDL_SetAlpha(surface, aflags, alpha); + /* Copy over the alpha channel */ + if (surface_flags & SDL_SRCALPHA) { + if (fmt->Amask) { + surface->flags &= ~SDL_SRCALPHA; + } else { + /* FIXME: Need to make sure the texture has an alpha channel + * and copy 'alpha' into the texture alpha channel. + */ + alpha = surface->format->alpha; + SDL_SetAlpha(surface, 0, 0); + } } - } - /* Update the texture */ - if (dst.flags & SDL_PREALLOC) { - SDL_UnlockTexture(textureID); - } else { + /* Copy over the image data */ + bounds.x = 0; + bounds.y = 0; + bounds.w = surface->w; + bounds.h = surface->h; + SDL_LowerBlit(surface, &bounds, &dst, &bounds); + + /* Clean up the original surface */ + if ((surface_flags & SDL_SRCALPHA) == SDL_SRCALPHA) { + Uint32 aflags = surface_flags & (SDL_SRCALPHA | SDL_RLEACCELOK); + if (fmt->Amask) { + surface->flags |= SDL_SRCALPHA; + } else { + SDL_SetAlpha(surface, aflags, alpha); + } + } + + /* Update the texture */ SDL_UpdateTexture(textureID, NULL, dst.pixels, dst.pitch); SDL_free(dst.pixels); + SDL_FreeFormat(dst.format); } - SDL_FreeFormat(dst.format); return textureID; } @@ -1967,6 +1978,10 @@ SDL_LockTexture(SDL_TextureID textureID, const SDL_Rect * rect, int markDirty, if (!texture) { return -1; } + if (texture->access != SDL_TEXTUREACCESS_STREAMING) { + SDL_SetError("SDL_LockTexture(): texture must be streaming"); + return -1; + } renderer = texture->renderer; if (!renderer->LockTexture) { @@ -1994,6 +2009,9 @@ SDL_UnlockTexture(SDL_TextureID textureID) if (!texture) { return; } + if (texture->access != SDL_TEXTUREACCESS_STREAMING) { + return; + } renderer = texture->renderer; if (!renderer->UnlockTexture) { @@ -2012,6 +2030,9 @@ SDL_DirtyTexture(SDL_TextureID textureID, int numrects, if (!texture) { return; } + if (texture->access != SDL_TEXTUREACCESS_STREAMING) { + return; + } renderer = texture->renderer; if (!renderer->DirtyTexture) { diff --git a/src/video/win32/SDL_d3drender.c b/src/video/win32/SDL_d3drender.c index 9cdb24e61..b17ad2542 100644 --- a/src/video/win32/SDL_d3drender.c +++ b/src/video/win32/SDL_d3drender.c @@ -459,7 +459,6 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) SDL_Window *window = SDL_GetWindowFromID(renderer->window); SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window); D3D_TextureData *data; - D3DPOOL pool; HRESULT result; data = (D3D_TextureData *) SDL_calloc(1, sizeof(*data)); @@ -470,22 +469,11 @@ D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) texture->driverdata = data; -#if 1 - /* FIXME: Do we want non-managed textures? - They need to be freed on device reset and then reloaded by the app... - */ - texture->access = SDL_TEXTUREACCESS_LOCAL; -#endif - if (texture->access == SDL_TEXTUREACCESS_LOCAL) { - pool = D3DPOOL_MANAGED; - } else { - pool = D3DPOOL_DEFAULT; - } result = IDirect3DDevice9_CreateTexture(renderdata->device, texture->w, texture->h, 1, 0, PixelFormatToD3DFMT(texture->format), - pool, &data->texture, NULL); + D3DPOOL_MANAGED, &data->texture, NULL); if (FAILED(result)) { D3D_SetError("CreateTexture()", result); return -1; @@ -628,11 +616,6 @@ D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, D3DLOCKED_RECT locked; HRESULT result; - if (texture->access != SDL_TEXTUREACCESS_LOCAL) { - SDL_SetError("Can't lock remote video memory"); - return -1; - } - d3drect.left = rect->x; d3drect.right = rect->x + rect->w; d3drect.top = rect->y; diff --git a/src/video/win32/SDL_gdirender.c b/src/video/win32/SDL_gdirender.c index 81b90482f..90e5c5776 100644 --- a/src/video/win32/SDL_gdirender.c +++ b/src/video/win32/SDL_gdirender.c @@ -304,7 +304,7 @@ GDI_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) } data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format)); - if (data->yuv || texture->access == SDL_TEXTUREACCESS_LOCAL + if (data->yuv || texture->access == SDL_TEXTUREACCESS_STREAMING || texture->format != display->current_mode.format) { int bmi_size; LPBITMAPINFO bmi; diff --git a/test/testsprite2.c b/test/testsprite2.c index 66d59a006..670957605 100644 --- a/test/testsprite2.c +++ b/test/testsprite2.c @@ -63,8 +63,7 @@ LoadSprite(char *file) /* Create textures from the image */ for (i = 0; i < state->num_windows; ++i) { SDL_SelectRenderer(state->windows[i]); - sprites[i] = - SDL_CreateTextureFromSurface(0, SDL_TEXTUREACCESS_REMOTE, temp); + sprites[i] = SDL_CreateTextureFromSurface(0, temp); if (!sprites[i]) { fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError()); SDL_FreeSurface(temp);