Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
slouken committed Aug 11, 2007
1 parent af45eda commit 10b8a74
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 294 deletions.
3 changes: 2 additions & 1 deletion include/SDL_compat.h
Expand Up @@ -36,14 +36,15 @@ 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
#define SDL_FULLSCREEN 0x00800000
#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 */

Expand Down
30 changes: 12 additions & 18 deletions include/SDL_video.h
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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.
Expand All @@ -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 */
Expand Down Expand Up @@ -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.
Expand All @@ -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);

Expand All @@ -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
*
Expand Down Expand Up @@ -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,
Expand All @@ -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()
Expand All @@ -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()
Expand Down Expand Up @@ -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);

/**
Expand Down
90 changes: 61 additions & 29 deletions src/SDL_compat.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 3 additions & 4 deletions src/video/SDL_RLEaccel.c
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down
34 changes: 25 additions & 9 deletions src/video/SDL_renderer_gl.c
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/video/SDL_renderer_sw.c
Expand Up @@ -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;
Expand Down

0 comments on commit 10b8a74

Please sign in to comment.