SDL2 source code analysis 5: Update texture (SDL_UpdateTexture ()),

Source: Internet
Author: User

SDL2 source code analysis 5: Update texture (SDL_UpdateTexture ()),

The previous article analyzed the texture creation function SDL_CreateTexture () of SDL (). This article continues to analyze the source code of SDL. This article analyzes the SDL_UpdateTexture () function of SDL to update texture data ().



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 4th SDL_CreateTexture () functions in the process (). This article continues to analyze the 5th functions SDL_UpdateTexture () in this process ().

Description of the SDL_UpdateTexture () function SDL uses SDL_UpdateTexture () to set the pixel data of the texture. SDL_UpdateTexture () is defined as follows.
int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,                                          const SDL_Rect * rect,                                              const void *pixels, int pitch);

The parameter description is as follows.

Texture: Target texture.

Rect: update the rectangular area of the pixel. Update the entire region when it is set to NULL.

Pixels: pixel data.

Pitch: the number of bytes of a row of pixel data.

If the call succeeds, 0 is returned. If the call fails,-1 is returned.


The call relationship between the SDL_UpdateTexture () 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/1793769

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

Source code analysis

The source code of SDL_UpdateTexture () is located in render \ SDL_render.c. As shown below.

int SDL_UpdateTexture(SDL_Texture * texture, const SDL_Rect * rect,                  const void *pixels, int pitch){    SDL_Renderer *renderer;    SDL_Rect full_rect;    CHECK_TEXTURE_MAGIC(texture, -1);    if (!pixels) {        return SDL_InvalidParamError("pixels");    }    if (!pitch) {        return SDL_InvalidParamError("pitch");    }    if (!rect) {        full_rect.x = 0;        full_rect.y = 0;        full_rect.w = texture->w;        full_rect.h = texture->h;        rect = &full_rect;    }    if (texture->yuv) {        return SDL_UpdateTextureYUV(texture, rect, pixels, pitch);    } else if (texture->native) {        return SDL_UpdateTextureNative(texture, rect, pixels, pitch);    } else {        renderer = texture->renderer;        return renderer->UpdateTexture(renderer, texture, rect, pixels, pitch);    }}

From the source code, we can see that the general process of SDL_UpdateTexture () 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. For some special formats, perform some processing:
A) if the input pixel data is in YUV format, SDL_UpdateTextureYUV () is called for processing.
B) if the pixel format of the input pixel data is not supported by the Renderer, SDL_UpdateTextureNative () is called for processing.
3. Call the UpdateTexture () method of SDL_Render to update the texture.This step is the core of the entire function.
Next we will take a detailed look at the UpdateTexture () methods of several different Renderer.

1. The UpdateTexture () function in Direct3DDirect3D Renderer is D3D_UpdateTexture (). Its source code is as follows (in render \ direct3d \ SDL_render_d3d.c ).
static intD3D_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,                  const SDL_Rect * rect, const void *pixels, int pitch){    D3D_TextureData *data = (D3D_TextureData *) texture->driverdata;    SDL_bool full_texture = SDL_FALSE;#ifdef USE_DYNAMIC_TEXTURE    if (texture->access == SDL_TEXTUREACCESS_STREAMING &&        rect->x == 0 && rect->y == 0 &&        rect->w == texture->w && rect->h == texture->h) {        full_texture = SDL_TRUE;    }#endif    if (!data) {        SDL_SetError("Texture is not currently available");        return -1;    }    if (D3D_UpdateTextureInternal(data->texture, texture->format, full_texture, rect->x, rect->y, rect->w, rect->h, pixels, pitch) < 0) {        return -1;    }    if (data->yuv) {        /* Skip to the correct offset into the next texture */        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->vtexture : data->utexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {            return -1;        }        /* Skip to the correct offset into the next texture */        pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);        if (D3D_UpdateTextureInternal(texture->format == SDL_PIXELFORMAT_YV12 ? data->utexture : data->vtexture, texture->format, full_texture, rect->x / 2, rect->y / 2, rect->w / 2, rect->h / 2, pixels, pitch / 2) < 0) {            return -1;        }    }    return 0;}


The Code shows that this function calls the D3D_UpdateTextureInternal () function. Note that if the input pixel format is YUV, three textures are used and the two textures are processed separately. The code for calling the function D3D_UpdateTextureInternal () is as follows.

static int D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool full_texture, int x, int y, int w, int h, const void *pixels, int pitch){    RECT d3drect;    D3DLOCKED_RECT locked;    const Uint8 *src;    Uint8 *dst;    int row, length;    HRESULT result;    if (full_texture) {        result = IDirect3DTexture9_LockRect(texture, 0, &locked, NULL, D3DLOCK_DISCARD);    } else {        d3drect.left = x;        d3drect.right = x + w;        d3drect.top = y;        d3drect.bottom = y + h;        result = IDirect3DTexture9_LockRect(texture, 0, &locked, &d3drect, 0);    }    if (FAILED(result)) {        return D3D_SetError("LockRect()", result);    }    src = (const Uint8 *)pixels;    dst = locked.pBits;    length = w * SDL_BYTESPERPIXEL(format);    if (length == pitch && length == locked.Pitch) {        SDL_memcpy(dst, src, length*h);    } else {        if (length > pitch) {            length = pitch;        }        if (length > locked.Pitch) {            length = locked.Pitch;        }        for (row = 0; row < h; ++row) {            SDL_memcpy(dst, src, length);            src += pitch;            dst += locked.Pitch;        }    }    IDirect3DTexture9_UnlockRect(texture, 0);    return 0;}


From the code, we can see that this function first calls IDirect3DTexture9_LockRect () to lock the texture, and then uses SDL_memcpy () to copy the new pixel data to the texture (SDL_memcpy () is actually memcpy ()), finally, use IDirect3DTexture9_UnlockRect () to unlock the texture. 2. The UpdateTexture () function in the OpenGLOpenGL Renderer is GL_UpdateTexture (). Its source code is as follows (in render \ opengl \ SDL_render_gl.c ).
static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,                 const SDL_Rect * rect, const void *pixels, int pitch){    GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;    GL_TextureData *data = (GL_TextureData *) texture->driverdata;    GL_ActivateRenderer(renderer);    renderdata->glEnable(data->type);    renderdata->glBindTexture(data->type, data->texture);    renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);    renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,                              (pitch / SDL_BYTESPERPIXEL(texture->format)));    renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,                                rect->h, data->format, data->formattype,                                pixels);    if (data->yuv) {        renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2));        /* Skip to the correct offset into the next texture */        pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);        if (texture->format == SDL_PIXELFORMAT_YV12) {            renderdata->glBindTexture(data->type, data->vtexture);        } else {            renderdata->glBindTexture(data->type, data->utexture);        }        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,                                    rect->w/2, rect->h/2,                                    data->format, data->formattype, pixels);        /* Skip to the correct offset into the next texture */        pixels = (const void*)((const Uint8*)pixels + (rect->h * pitch)/4);        if (texture->format == SDL_PIXELFORMAT_YV12) {            renderdata->glBindTexture(data->type, data->utexture);        } else {            renderdata->glBindTexture(data->type, data->vtexture);        }        renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,                                    rect->w/2, rect->h/2,                                    data->format, data->formattype, pixels);    }    renderdata->glDisable(data->type);    return GL_CheckError("glTexSubImage2D()", renderer);}

From the code, we can see that this function calls the OpenGL API functions glBindTexture () and glTexSubImage2D () to update a texture.
Note that if the input pixel format is YUV, three textures are used and the two textures are processed separately. 3. The UpdateTexture () function in the SoftwareSoftware Renderer is SW_UpdateTexture (), and its source code is as follows (in render \ software \ SDL_render_sw.c ).
static int SW_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,                 const SDL_Rect * rect, const void *pixels, int pitch){    SDL_Surface *surface = (SDL_Surface *) texture->driverdata;    Uint8 *src, *dst;    int row;    size_t length;    if(SDL_MUSTLOCK(surface))        SDL_LockSurface(surface);    src = (Uint8 *) pixels;    dst = (Uint8 *) surface->pixels +                        rect->y * surface->pitch +                        rect->x * surface->format->BytesPerPixel;    length = rect->w * surface->format->BytesPerPixel;    for (row = 0; row < rect->h; ++row) {        SDL_memcpy(dst, src, length);        src += pitch;        dst += surface->pitch;    }    if(SDL_MUSTLOCK(surface))        SDL_UnlockSurface(surface);    return 0;}

The source code of the function has not been analyzed in detail. The most critical function is SDL_memcpy (), which updates the pixel data of the texture. But does the Software Renderer need Lock () and Unlock () for texture modification? This 1.1 straight is not too clear.




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.