SDL_Texture
SDL_Texture结构定义了一个SDL中的纹理。
/**
* An efficient driver-specific representation of pixel data
*/
struct SDL_Texture;
typedef struct SDL_Texture SDL_Texture;
在源代码工程中可以看到SDL_Texture的定义,位于render\SDL_sysrender.h文件中。它的定义如下。
/* 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 */
SDL_ScaleMode scaleMode; /**< The texture scale 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;
SDL_Surface *locked_surface; /**< Locked region exposed as a SDL surface */
Uint32 last_command_generation; /* last command queue generation this texture was in. */
void *driverdata; /**< Driver specific texture representation */
SDL_Texture *prev;
SDL_Texture *next;
};
可以看出其中包含了一个“纹理”所具备的各种属性。下面来看看如何创建这个SDL_Texture。
SDL_CreateTexture()
函数简介
使用SDL_CreateTexture()基于渲染器创建一个纹理。SDL_CreateTexture()的原型如下。
SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,
Uint32 format,
int access, int w,
int h);
参数的含义如下。
renderer:目标渲染器。
format :纹理的格式。后面会详述。
access :可以取以下值(定义位于SDL_TextureAccess中)
SDL_TEXTUREACCESS_STATIC :变化极少
SDL_TEXTUREACCESS_STREAMING :变化频繁
SDL_TEXTUREACCESS_TARGET :暂时没有理解
w :纹理的宽
h :纹理的高
创建成功则返回纹理的ID,失败返回0。
源代码分析
SDL_CreateTexture()的源代码位于render\SDL_render.c中。如下所示。
SDL_Texture *
SDL_CreateTexture(SDL_Renderer * renderer, Uint32 format, int access, int w, int h)
{
SDL_Texture *texture;
SDL_bool texture_is_fourcc_and_target;
CHECK_RENDERER_MAGIC(renderer, NULL);
if (!format) {
format = renderer->info.texture_formats[0];
}
if (SDL_BYTESPERPIXEL(format) == 0) {
SDL_SetError("Invalid texture format");
return NULL;
}
if (SDL_ISPIXELFORMAT_INDEXED(format)) {
SDL_SetError("Palettized textures are 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 are limited to %dx%d", renderer->info.max_texture_width, renderer->info.max_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->scaleMode = SDL_GetScaleMode();
texture->renderer = renderer;
texture->next = renderer->textures;
if (renderer->textures) {
renderer->textures->prev = texture;
}
renderer->textures = texture;
/* FOURCC format cannot be used directly by renderer back-ends for target texture */
texture_is_fourcc_and_target = (access == SDL_TEXTUREACCESS_TARGET && SDL_ISPIXELFORMAT_FOURCC(texture->format));
if (texture_is_fourcc_and_target == SDL_FALSE && IsSupportedFormat(renderer, format)) {
if (renderer->CreateTexture(renderer, texture) < 0) {
SDL_DestroyTexture(texture);
return NULL;
}
} else {
int closest_format;
if (texture_is_fourcc_and_target == SDL_FALSE) {
closest_format = GetClosestSupportedFormat(renderer, format);
} else {
closest_format = renderer->info.texture_formats[0];
}
texture->native = SDL_CreateTexture(renderer, closest_format, access, w, h);
if (!texture->native) {
SDL_DestroyTexture(texture);
return NULL;
}
/* Swap textures to have 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)) {
#if SDL_HAVE_YUV
texture->yuv = SDL_SW_CreateYUVTexture(format, w, h);
#else
SDL_SetError("SDL not built with YUV support");
#endif
if (!texture->yuv) {
SDL_DestroyTexture(texture);
return NULL;
}
} else if (access == SDL_TEXTUREACCESS_STREAMING) {
/* The pitch is 4 byte aligned */
texture->pitch = (((w * SDL_BYTESPERPIXEL(format)) + 3) & ~3);
texture->pixels = SDL_calloc(1, texture->pitch * h);
if (!texture->pixels) {
SDL_DestroyTexture(texture);
return NULL;
}
}
}
return texture;
}
从源代码中可以看出,SDL_CreateTexture()的大致流程如下。
-
检查输入参数的合理性。例如像素格式是否支持,宽和高是否小于等于0等等。
-
新建一个SDL_Texture。调用SDL_calloc()(实际上就是calloc())为新建的SDL_Texture分配内存。
-
调用SDL_Render的CreateTexture()方法创建纹理。这一步是整个函数的核心。
参考文献
1、https://blog.csdn.net/leixiaohua1020/article/details/40743061