SDL2 source code analysis 4: texture (SDL_Texture), sdl2sdl_texture

Source: Internet
Author: User

SDL2 source code analysis 4: texture (SDL_Texture), sdl2sdl_texture
The previous article analyzed the SDL_CreateRenderer () function used to create a Renderer in SDL (). This article continues to analyze the source code of SDL. This document analyzes the SDL texture (SDL_Texture ).



The code process for playing a video by using SDL is as follows.
Initialization:

SDL_Init (): Initialize SDL.
SDL_CreateWindow (): create a Window ).
SDL_CreateRenderer (): Creates a Renderer (Render) based on the window ).
SDL_CreateTexture (): Creates a Texture (Texture ).
Loop rendering data:
SDL_UpdateTexture (): Specifies the texture data.
SDL_RenderCopy (): Copies the texture to the Renderer.

SDL_RenderPresent (): display.

The previous article analyzed the 3rd SDL_CreateRenderer () functions in the process (). This article continues to analyze the 4th function SDL_CreateTexture () in this process ().


SDL_Texture

The SDL_Texture structure defines the texture in an SDL. If SDL2 compiled SDK is used directly, the internal structure of SDL_Texture is invisible. Only one line of code is defined 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;

In the source code project, you can see the definition of SDL_Texture, 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;};

It can be seen that it contains various attributes of a "texture. Next let's take a look at how to create this SDL_Texture.

SDL_CreateTexture () Function IntroductionUse SDL_CreateTexture () to create a texture based on the Renderer. SDL_CreateTexture () is defined as follows.
SDL_Texture * SDLCALL SDL_CreateTexture(SDL_Renderer * renderer,                                                        Uint32 format,                                                        int access, int w,                                                        int h);

The parameter description is as follows.

Renderer: Target renderer.

Format: Specifies the texture format. It will be detailed later.

Access: You can obtain the following values (defined in SDL_TextureAccess)

SDL_TEXTUREACCESS_STATIC: Few changes
SDL_TEXTUREACCESS_STREAMING: frequent changes

SDL_TEXTUREACCESS_TARGET: not understood yet

W: texture width

H: texture height

If the creation is successful, the texture ID is returned. If the creation fails, 0 is returned.


Function call Relationship Diagram

The call relationship between the SDL _ CreateTexture () key functions can be expressed.

 

The above picture is not clear, and the clearer picture is uploaded to the album:

Http://my.csdn.net/leixiaohua1020/album/detail/1793543

Save the image in the album to get a clear image.


Source code analysis

The source code of 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 *texture;    CHECK_RENDERER_MAGIC(renderer, NULL);    if (!format) {        format = renderer->info.texture_formats[0];    }    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->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,                                GetClosestSupportedFormat(renderer, 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)) {            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 */            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;}

From the source code, we can see that the general process of SDL_CreateTexture () is as follows.

1. Check the rationality of the input parameters.For example, whether the pixel format is supported, and whether the width and height are less than or equal to 0.

2. Create an SDL_Texture.Call SDL_calloc () (actually calloc () to allocate memory for the newly created SDL_Texture.

3. Call the CreateTexture () method of SDL_Render to create a texture.This step is the core of the entire function.

Next we will take a detailed look at the CreateTexture () methods of several different Renderer.

1. The CreateTexture () function in the Direct3DDirect3D Renderer is D3D_CreateTexture (). Its source code is as follows (in render \ direct3d \ SDL_render_d3d.c ).
static int D3D_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture){    D3D_RenderData *renderdata = (D3D_RenderData *) 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 D3DUSAGE_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->format),                                           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;}

The Code shows that this function calls the Direct3D API function IDirect3DDevice9_CreateTexture () to create a texture.

2. OpenGL

The CreateTexture () function in the OpenGL Renderer is GL_CreateTexture (), and its source code is as follows (in render \ opengl \ SDL_render_gl.c ).

static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture){    GL_RenderData *renderdata = (GL_RenderData *) 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_GetPixelFormatName(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->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_TARGET */){        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 is 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#ifndef 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) {        renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,                                    GL_STORAGE_SHARED_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->format)));        renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,                                 texture_h, 0, format, 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_EDGE);        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_EDGE);        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);}

The Code shows that this function calls the OpenGL API function glGenTextures () and glBindTexture () to create a texture. You can use glTexParameteri () to set relevant parameters.

Note that in the OpenGL Renderer, if the input pixel format is YV12 or IYUV, three textures are used.

3. Software

The CreateTexture () function 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 of the function has not been analyzed in detail. We can see that "Surface" is created by calling SDL_CreateRGBSurface ".




Source code of java programming ideology version 4th

I have 1-4 chapters. Do you want? Leave a mailbox.
 
Android401 source code Problems

First of all, this idea is incorrect, or imperfect. After you double-click it, if there is a task in the stack and there is already an Activity running, press the Home Key for the first time to return to the desktop. at an interval of MS, click the second button to return to the original program interface, or display the latest task?
Then, if you want to modify the source code path/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager. java. The Home operation is provided here. The method for modifying luanch is launchHomeFromHotKey (). The operation you need is changed here.
Finally, there is another way of thinking, that is, to completely modify the Home listener and keep the execution method unchanged, so that LongPress is equal to DoubleClick. However, this operation may cause many problems and should be used with caution ..
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.