=====================================================
SDL Source Code Analysis series articles list:
SDL2 Source Code Analysis 1: Initialize (Sdl_init ())
SDL2 Source Code Analysis 2: Window (Sdl_window)
SDL2 Source Code Analysis 3: Renderer (Sdl_renderer)
SDL2 Source Code Analysis 4: Textures (sdl_texture)
SDL2 Source Code Analysis 5: Update textures (sdl_updatetexture ())
SDL2 Source Code Analysis 6: Copy to Renderer (Sdl_rendercopy ())
SDL2 Source Code Analysis 7: Display (Sdl_renderpresent ())
SDL2 Source Code Analysis 8: Video Display summary
=====================================================
The previous article analyzed the function sdl_createrenderer () that created the renderer in SDL. This article continues to analyze the source code of the SDL. This article analyzes the SDL texture (sdl_texture).
The code flow for the SDL playback video is as follows.
Initialize:
Sdl_init (): Initialize SDL.
Sdl_createwindow (): Create window (Windows).
Sdl_createrenderer (): Creates a renderer (render) based on a window.
Sdl_createtexture (): Creates a texture (Texture). To iterate over the rendered data:
Sdl_updatetexture (): Sets the data for the texture.
Sdl_rendercopy (): Textures are copied to the renderer.
Sdl_renderpresent (): Display. The 3rd function in this process, Sdl_createrenderer (), was analyzed in the previous article. This article continues to analyze the 4th function sdl_createtexture () in the process.
sdl_texture
The sdl_texture structure defines a texture in the SDL. If you use SDL2 compiled SDK directly, you can not see the internal structure of sdl_texture. The definition for it has only one line of code in the header file, as shown below.
/**
* \brief An efficient driver-specific representation of pixel data
*/
struct sdl_texture;
typedef struct SDL_TEXTURE sdl_texture;
You can see the definition of sdl_texture in the source code project, which is located in the Render\sdl_sysrender.h file. It is defined as follows.
/* Define the SDL texture structure */
struct sdl_texture
{
const void *magic;
Uint32 format; /**< the pixel format of the texture */
int access; /**< sdl_textureaccess */
int w; /**< the width of the texture */
int h; /**< the height of the texture */
int modmode; /**< the texture modulation mode */
sdl_blendmode Blendmode; /**< the texture blend mode */
Uint8 R, G, B, A; /**< Texture Modulation values */
sdl_renderer *renderer;
/* Support for formats not supported directly by the renderer */
sdl_texture *native;
Sdl_sw_yuvtexture *yuv;
void *pixels;
int pitch;
Sdl_rect Locked_rect;
void *driverdata; /**< Driver Specific Texture representation * *
sdl_texture *prev;
Sdl_texture *next;
};
You can see that it contains a variety of properties that a "texture" has. Here's a look at how to create this sdl_texture.
sdl_createtexture () Introduction to Functions use Sdl_createtexture () to create a texture based on the renderer. The prototype of Sdl_createtexture () is as follows.
Sdl_texture * Sdlcall sdl_createtexture (sdl_renderer * Renderer,
Uint32 format,
int access, int w,
int h);
The meaning of the parameter is as follows.
Renderer: Target renderer. Format: The formatting of the texture. It will be detailed later.
Access: You can take the following values (defined in sdl_textureaccess) Sdl_textureaccess_static: Very little change
Sdl_textureaccess_streaming: Frequent changes
Sdl_textureaccess_target: No understanding for the time being
W: width of the texture
H: High Texture
Successful creation returns the ID of the texture, and the failure returns 0.
function Call Graph
Sdl_ createtexture () the invocation relationship of key functions can be represented in the following diagram.
The picture above is not very clear, and a clearer picture is uploaded to the album:
http://my.csdn.net/leixiaohua1020/album/detail/1793543
Save the pictures in the album to get a clear picture.
Source Code Analysis
The source code for Sdl_createtexture () is located in Render\sdl_render.c. as shown below.
Sdl_texture * Sdl_createtexture (Sdl_renderer * Renderer, Uint32 format, int access, int w, int h) {Sdl_texture *textu
Re
Check_renderer_magic (RENDERER, NULL);
if (!format) {format = renderer->info.texture_formats[0];
} if (sdl_ispixelformat_indexed (format)) {Sdl_seterror ("palettized textures is not supported");
return NULL;
} if (w <= 0 | | h <= 0) {sdl_seterror ("Texture dimensions can ' t be 0");
return NULL;
} if ((Renderer->info.max_texture_width && w > renderer->info.max_texture_width) | | (renderer->info.max_texture_height && H > Renderer->info.max_texture_height)) {Sdl_seterror ("Texture dimensions is limited to%dx%d", Renderer->info.max_texture_width, RENDERER->INFO.M
Ax_texture_height);
return NULL;
} texture = (Sdl_texture *) sdl_calloc (1, sizeof (*texture));
if (!texture) {sdl_outofmemory (); RetuRN NULL;
} texture->magic = &texture_magic;
Texture->format = format;
texture->access = Access;
Texture->w = W;
Texture->h = h;
Texture->r = 255;
Texture->g = 255;
Texture->b = 255;
Texture->a = 255;
Texture->renderer = renderer;
Texture->next = renderer->textures;
if (renderer->textures) {renderer->textures->prev = texture;
} renderer->textures = texture;
if (Issupportedformat (renderer, format)) {if (renderer->createtexture (renderer, Texture) < 0) {
Sdl_destroytexture (texture);
return 0; }} else {texture->native = Sdl_createtexture (renderer, Getclosestsupporte
Dformat (renderer, format), Access, W, h);
if (!texture->native) {sdl_destroytexture (texture);
return NULL; }/* Swap textures to having texture before texture->native in the list */Texture->native->next = texture->next;
if (texture->native->next) {Texture->native->next->prev = texture->native;
} Texture->prev = texture->native->prev;
if (texture->prev) {texture->prev->next = texture;
} Texture->native->prev = texture;
Texture->next = texture->native;
Renderer->textures = texture;
if (SDL_ISPIXELFORMAT_FOURCC (Texture->format)) {TEXTURE->YUV = sdl_sw_createyuvtexture (format, W, h);
if (!TEXTURE->YUV) {sdl_destroytexture (texture);
return NULL; }} else if (Access = = sdl_textureaccess_streaming) {/* The pitch is 4 byte aligned */TE
Xture->pitch = (((w * sdl_bytesperpixel (format)) + 3) &); Texture->pixels = SDL_calloc (1, Texture->pitch * h);
if (!texture->pixels) {sdl_destroytexture (texture);
return NULL;
}}} return texture; }
As you can see from the source code, the approximate flow of sdl_createtexture () is as follows.
1. Check the rationality of the input parameters. For example, whether the pixel format is supported, width and height is less than or equal to 0, etc.
2. Create a new sdl_texture. Call Sdl_calloc () (actually calloc ()) to allocate memory for the newly created sdl_texture.
3. Call Sdl_render's CreateTexture () method to create the texture. This step is the core of the whole function.
Let's take a look at a couple of different renderer createtexture () methods. 1.the function for CreateTexture () in the Direct3D Direct3D renderer is D3d_createtexture (), and its source code is shown below (in Render\direct3d\sdl_render _D3D.C).
static int D3d_createtexture (Sdl_renderer * Renderer, Sdl_texture * Texture) {D3d_renderdata *renderdata = (d3d_rende
RData *) renderer->driverdata;
D3d_texturedata *data;
D3dpool Pool;
DWORD usage;
HRESULT result;
data = (D3d_texturedata *) sdl_calloc (1, sizeof (*data));
if (!data) {return sdl_outofmemory ();
} Data->scalemode = Getscalequality ();
Texture->driverdata = data;
#ifdef use_dynamic_texture if (texture->access = = sdl_textureaccess_streaming) {pool = D3dpool_default;
Usage = d3dusage_dynamic; } else #endif if (texture->access = = Sdl_textureaccess_target) {/* d3dpool_managed does not work with D3DU
Sage_rendertarget */pool = D3dpool_default;
Usage = d3dusage_rendertarget;
} else {pool = d3dpool_managed;
Usage = 0;
} result = Idirect3ddevice9_createtexture (Renderdata->device, Texture->w, Texture->h, 1, usage, pixelformattod3dfmt (Texture->format),
Pool, &data->texture, NULL);
if (FAILED (Result)) {return D3d_seterror ("CreateTexture ()", result);
} if (Texture->format = = SDL_PIXELFORMAT_YV12 | |
Texture->format = = SDL_PIXELFORMAT_IYUV) {DATA->YUV = Sdl_true;
result = Idirect3ddevice9_createtexture (Renderdata->device, TEXTURE->W/2, TEXTURE->H/2, 1, usage, PIXELFORMATTOD3DFMT (texture->for
MAT), pool, &data->utexture, NULL);
if (FAILED (Result)) {return D3d_seterror ("CreateTexture ()", result);
} result = Idirect3ddevice9_createtexture (Renderdata->device, TEXTURE->W/2, TEXTURE->H/2, 1, usage, PIXELFORMATTOD3DFMT (texture->format
), pool, &data->vtexture, NULL);
if (FAILED (Result)) {return D3d_seterror ("CreateTexture ()", result);
}} return 0; }
As can be seen from the code, the function calls Direct3D's API function Idirect3ddevice9_createtexture () to create a texture.
2. OpenGL
The function that corresponds to CreateTexture () in the OpenGL renderer is gl_createtexture (), and its source code is as follows (located in RENDER\OPENGL\SDL_RENDER_GL.C).
static int Gl_createtexture (Sdl_renderer * Renderer, Sdl_texture * Texture) {Gl_renderdata *renderdata = (Gl_renderda
TA *) renderer->driverdata;
Gl_texturedata *data;
Glint Internalformat;
Glenum format, type;
int Texture_w, Texture_h;
Glenum ScaleMode;
Gl_activaterenderer (renderer); if (!convert_format (Renderdata, Texture->format, &internalformat, &format, &type)) {return Sdl_seterror ("Texture format%s not supported by OpenGL", Sdl_getpixelformatn
Ame (Texture->format));
} data = (Gl_texturedata *) sdl_calloc (1, sizeof (*data));
if (!data) {return sdl_outofmemory ();
} if (texture->access = = sdl_textureaccess_streaming) {size_t size;
Data->pitch = texture->w * Sdl_bytesperpixel (Texture->format);
Size = Texture->h * data->pitch;
if (Texture->format = = SDL_PIXELFORMAT_YV12 | | Texture->format = = SDL_PIXELFORMAT_IYUV) {/* need to add size for the U and V planes */size
+ = (2 * (TEXTURE->H * data->pitch)/4);
} data->pixels = Sdl_calloc (1, size);
if (!data->pixels) {sdl_free (data);
return Sdl_outofmemory (); }} if (texture->access = = sdl_textureaccess_target) {Data->fbo = Gl_getfbo (Renderdata, texture-&
Gt;w, texture->h);
} else {data->fbo = NULL;
} gl_checkerror ("", renderer);
Renderdata->glgentextures (1, &data->texture);
if (Gl_checkerror ("Glgentexures ()", renderer) < 0) {sdl_free (data);
return-1;
} texture->driverdata = data; if (renderdata->gl_arb_texture_rectangle_supported)/* && texture->access! = Sdl_textureaccess_targ
ET *) {data->type = Gl_texture_rectangle_arb;
Texture_w = texture->w; Texture_H = texture->h;
DATA->TEXW = (glfloat) texture_w;
DATA->TEXH = (glfloat) texture_h;
} else {data->type = gl_texture_2d;
Texture_w = Power_of_2 (texture->w);
Texture_h = Power_of_2 (texture->h);
DATA->TEXW = (glfloat) (texture->w)/texture_w;
DATA->TEXH = (glfloat) texture->h/texture_h;
} data->format = format;
Data->formattype = type;
ScaleMode = Getscalequality ();
Renderdata->glenable (Data->type);
Renderdata->glbindtexture (Data->type, data->texture);
Renderdata->gltexparameteri (Data->type, Gl_texture_min_filter, ScaleMode);
Renderdata->gltexparameteri (Data->type, Gl_texture_mag_filter, ScaleMode); /* According to the spec, Clamp_to_edge are the default for Texture_rectangle and setting it causes an Invalid_enum
Error in the latest NVidia drivers. */if (data->type! = Gl_texture_rectangle_arb) {RendeRdata->gltexparameteri (Data->type, gl_texture_wrap_s, Gl_clamp_to_edge);
Renderdata->gltexparameteri (Data->type, gl_texture_wrap_t, Gl_clamp_to_edge); } #ifdef __macosx__ #ifndef gl_texture_storage_hint_apple #define Gl_texture_storage_hint_apple 0X85BC #endif #i Fndef storage_cached_apple #define Storage_cached_apple 0x85be #endif #ifndef storage_shared_apple #define Storage_shared_apple 0x85bf #endif if (texture->access = = sdl_textureaccess_streaming) {ren Derdata->gltexparameteri (Data->type, Gl_texture_storage_hint_apple, gl_storage_s
Hared_apple);
} else {renderdata->gltexparameteri (Data->type, Gl_texture_storage_hint_apple,
Gl_storage_cached_apple); } if (texture->access = = sdl_textureaccess_streaming && texture->Format = = sdl_pixelformat_argb8888 && (texture->w% 8) = = 0) {Renderdata->glpixelstorei (gl_
Unpack_client_storage_apple, gl_true);
Renderdata->glpixelstorei (gl_unpack_alignment, 1); Renderdata->glpixelstorei (Gl_unpack_row_length, (Data->pitch/sdl_bytesperpixel (texture-&
(Gt;format))); Renderdata->glteximage2d (data->type, 0, Internalformat, Texture_w, Texture_h, 0, FO
Rmat, type, data->pixels);
Renderdata->glpixelstorei (Gl_unpack_client_storage_apple, Gl_false);
} else #endif {renderdata->glteximage2d (data->type, 0, Internalformat, Texture_w,
Texture_h, 0, format, type, NULL);
} renderdata->gldisable (Data->type);
if (Gl_checkerror ("glteximage2d ()", renderer) < 0) {return-1;
} if (Texture->format = = SDL_PIXELFORMAT_YV12 | | Texture->format = = SDL_PIXELFORMAT_IYUV) {DATA->YUV = Sdl_true;
Renderdata->glgentextures (1, &data->utexture);
Renderdata->glgentextures (1, &data->vtexture);
Renderdata->glenable (Data->type);
Renderdata->glbindtexture (Data->type, data->utexture);
Renderdata->gltexparameteri (Data->type, Gl_texture_min_filter, ScaleMode);
Renderdata->gltexparameteri (Data->type, Gl_texture_mag_filter, ScaleMode); Renderdata->gltexparameteri (Data->type, gl_texture_wrap_s, gl_clamp_to_e
DGE);
Renderdata->gltexparameteri (Data->type, gl_texture_wrap_t, Gl_clamp_to_edge); Renderdata->glteximage2d (data->type, 0, Internalformat, TEXTURE_W/2, texture
_H/2, 0, format, type, NULL); Renderdata-> Glbindtexture (Data->type, data->vtexture);
Renderdata->gltexparameteri (Data->type, Gl_texture_min_filter, ScaleMode);
Renderdata->gltexparameteri (Data->type, Gl_texture_mag_filter, ScaleMode); Renderdata->gltexparameteri (Data->type, gl_texture_wrap_s, gl_clamp_to_e
DGE);
Renderdata->gltexparameteri (Data->type, gl_texture_wrap_t, Gl_clamp_to_edge); Renderdata->glteximage2d (data->type, 0, Internalformat, TEXTURE_W/2, texture
_H/2, 0, format, type, NULL);
Renderdata->gldisable (Data->type); } return Gl_checkerror ("", renderer);}
As can be seen from the code, the function calls OpenGL's API function Glgentextures () and Glbindtexture () creates a texture. And some parameters are set with Gltexparameteri ().
One thing to note here is that in the OpenGL renderer, if the input pixel format is YV12 or IYUV, 3 textures will be used. 3. Software
The function that corresponds to CreateTexture () in the software renderer is sw_createtexture (), and its source code is as follows (in RENDER\SOFTWARE\SDL_RENDER_SW.C).
static int Sw_createtexture (Sdl_renderer * Renderer, Sdl_texture * Texture)
{
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
if (! Sdl_pixelformatenumtomasks
(Texture->format, &BPP, &rmask, &gmask, &bmask, &Amask)) {
return Sdl_seterror ("Unknown texture format");
}
Texture->driverdata =
sdl_creatergbsurface (0, Texture->w, Texture->h, BPP, Rmask, Gmask,
Bmask, Amask);
Sdl_setsurfacecolormod (Texture->driverdata, Texture->r, Texture->g,
texture->b);
Sdl_setsurfacealphamod (Texture->driverdata, texture->a);
Sdl_setsurfaceblendmode (Texture->driverdata, texture->blendmode);
if (texture->access = = sdl_textureaccess_static) {
Sdl_setsurfacerle (texture->driverdata, 1);
}
if (!texture->driverdata) {
return-1;
}
return 0;
}
The source code for this function has not been analyzed in detail. You can see that Sdl_creatergbsurface () was called to create "Surface".