日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy())

發布時間:2025/4/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy()) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

=====================================================

SDL源碼分析系列文章列表:

SDL2源碼分析1:初始化(SDL_Init())

SDL2源碼分析2:窗體(SDL_Window)

SDL2源碼分析3:渲染器(SDL_Renderer)

SDL2源碼分析4:紋理(SDL_Texture)

SDL2源碼分析5:更新紋理(SDL_UpdateTexture())

SDL2源碼分析6:拷貝到渲染器(SDL_RenderCopy())

SDL2源碼分析7:顯示(SDL_RenderPresent())

SDL2源碼分析8:視頻顯示總結

=====================================================


上一篇文章分析了SDL更新紋理像素數據的函數SDL_UpdateTexture()。這篇文章繼續分析SDL的源碼。本文分析SDL紋理拷貝到渲染目標的函數SDL_RenderCopy()。



?


SDL播放視頻的代碼流程例如以下所看到的。


初始化:?

SDL_Init(): 初始化SDL。?
SDL_CreateWindow(): 創建窗體(Window)。?
SDL_CreateRenderer(): 基于窗體創建渲染器(Render)。?
SDL_CreateTexture(): 創建紋理(Texture)。

?

循環渲染數據:?
SDL_UpdateTexture(): 設置紋理的數據。?
SDL_RenderCopy(): 紋理復制給渲染器。?
SDL_RenderPresent(): 顯示。上篇文章分析了該流程中的第5個函數SDL_UpdateTexture()。本文繼續分析該流程中的第6個函數SDL_RenderCopy()。


SDL_RenderCopy()

函數簡單介紹

SDL使用SDL_RenderCopy()將紋理數據復制給渲染目標。SDL_RenderCopy()的原型例如以下。

int SDLCALL SDL_RenderCopy(SDL_Renderer * renderer,SDL_Texture * texture,const SDL_Rect * srcrect,const SDL_Rect * dstrect);
參數的含義例如以下。
renderer:渲染目標。
texture:輸入紋理。
srcrect:選擇輸入紋理的一塊矩形區域作為輸入。設置為NULL的時候整個紋理作為輸入。
dstrect:選擇渲染目標的一塊矩形區域作為輸出。設置為NULL的時候整個渲染目標作為輸出。



成功的話返回0,失敗的話返回-1。


函數調用關系圖

SDL_RenderCopy()關鍵函數的調用關系能夠用下圖表示。


上面的圖片不太清晰,更清晰的圖片上傳到了相冊里面:

http://my.csdn.net/leixiaohua1020/album/detail/1793911

把相冊里面的圖片保存下來就能夠得到清晰的圖片了。


源碼分析

SDL_RenderCopy()的源碼位于render\SDL_render.c中。例如以下所看到的。

int SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,const SDL_Rect * srcrect, const SDL_Rect * dstrect) {SDL_Rect real_srcrect = { 0, 0, 0, 0 };SDL_Rect real_dstrect = { 0, 0, 0, 0 };SDL_FRect frect;CHECK_RENDERER_MAGIC(renderer, -1);CHECK_TEXTURE_MAGIC(texture, -1);if (renderer != texture->renderer) {return SDL_SetError("Texture was not created with this renderer");}real_srcrect.x = 0;real_srcrect.y = 0;real_srcrect.w = texture->w;real_srcrect.h = texture->h;if (srcrect) {if (!SDL_IntersectRect(srcrect, &real_srcrect, &real_srcrect)) {return 0;}}SDL_RenderGetViewport(renderer, &real_dstrect);real_dstrect.x = 0;real_dstrect.y = 0;if (dstrect) {if (!SDL_HasIntersection(dstrect, &real_dstrect)) {return 0;}real_dstrect = *dstrect;}if (texture->native) {texture = texture->native;}/* Don't draw while we're hidden */if (renderer->hidden) {return 0;}frect.x = real_dstrect.x * renderer->scale.x;frect.y = real_dstrect.y * renderer->scale.y;frect.w = real_dstrect.w * renderer->scale.x;frect.h = real_dstrect.h * renderer->scale.y;return renderer->RenderCopy(renderer, texture, &real_srcrect, &frect); }

從源碼中能夠看出,SDL_RenderCopy()的大致流程例如以下。

1. 檢查輸入參數的合理性。
2. 調用SDL_Render的RenderCopy ()方法復制紋理到渲染目標。

這一步是整個函數的核心。


以下我們具體看一下幾種不同的渲染器的RenderCopy()的方法。

1. Direct3D

Direct3D 渲染器中相應RenderCopy()的函數是D3D_RenderCopy(),它的源碼例如以下所看到的(位于render\direct3d\SDL_render_d3d.c)。
static int D3D_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,const SDL_Rect * srcrect, const SDL_FRect * dstrect) {D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;D3D_TextureData *texturedata;LPDIRECT3DPIXELSHADER9 shader = NULL;float minx, miny, maxx, maxy;float minu, maxu, minv, maxv;DWORD color;Vertex vertices[4];HRESULT result;if (D3D_ActivateRenderer(renderer) < 0) {return -1;}texturedata = (D3D_TextureData *)texture->driverdata;if (!texturedata) {SDL_SetError("Texture is not currently available");return -1;}minx = dstrect->x - 0.5f;miny = dstrect->y - 0.5f;maxx = dstrect->x + dstrect->w - 0.5f;maxy = dstrect->y + dstrect->h - 0.5f;minu = (float) srcrect->x / texture->w;maxu = (float) (srcrect->x + srcrect->w) / texture->w;minv = (float) srcrect->y / texture->h;maxv = (float) (srcrect->y + srcrect->h) / texture->h;color = D3DCOLOR_ARGB(texture->a, texture->r, texture->g, texture->b);vertices[0].x = minx;vertices[0].y = miny;vertices[0].z = 0.0f;vertices[0].color = color;vertices[0].u = minu;vertices[0].v = minv;vertices[1].x = maxx;vertices[1].y = miny;vertices[1].z = 0.0f;vertices[1].color = color;vertices[1].u = maxu;vertices[1].v = minv;vertices[2].x = maxx;vertices[2].y = maxy;vertices[2].z = 0.0f;vertices[2].color = color;vertices[2].u = maxu;vertices[2].v = maxv;vertices[3].x = minx;vertices[3].y = maxy;vertices[3].z = 0.0f;vertices[3].color = color;vertices[3].u = minu;vertices[3].v = maxv;D3D_SetBlendMode(data, texture->blendMode);D3D_UpdateTextureScaleMode(data, texturedata, 0);result =IDirect3DDevice9_SetTexture(data->device, 0, (IDirect3DBaseTexture9 *)texturedata->texture);if (FAILED(result)) {return D3D_SetError("SetTexture()", result);}if (texturedata->yuv) {shader = data->ps_yuv;D3D_UpdateTextureScaleMode(data, texturedata, 1);D3D_UpdateTextureScaleMode(data, texturedata, 2);result =IDirect3DDevice9_SetTexture(data->device, 1, (IDirect3DBaseTexture9 *)texturedata->utexture);if (FAILED(result)) {return D3D_SetError("SetTexture()", result);}result =IDirect3DDevice9_SetTexture(data->device, 2, (IDirect3DBaseTexture9 *)texturedata->vtexture);if (FAILED(result)) {return D3D_SetError("SetTexture()", result);}}if (shader) {result = IDirect3DDevice9_SetPixelShader(data->device, shader);if (FAILED(result)) {return D3D_SetError("SetShader()", result);}}result =IDirect3DDevice9_DrawPrimitiveUP(data->device, D3DPT_TRIANGLEFAN, 2,vertices, sizeof(*vertices));if (FAILED(result)) {return D3D_SetError("DrawPrimitiveUP()", result);}if (shader) {result = IDirect3DDevice9_SetPixelShader(data->device, NULL);if (FAILED(result)) {return D3D_SetError("SetShader()", result);}}return 0; }

從代碼中能夠看出,D3D_RenderCopy()函數依照運行的順序調用了例如以下函數:

D3D_ActivateRenderer():激活渲染器。

其內部使用Direct3D的API函數IDirect3DDevice9_BeginScene()開始一個D3D的場景。
D3D_SetBlendMode():設置渲染器狀態。

其內部使用Direct3D的API函數IDirect3DDevice9_SetRenderState()設置渲染器的狀態。


D3D_UpdateTextureScaleMode():設置紋理採樣方式。其內部調用使用Direct3D的API函數IDirect3DDevice9_SetSamplerState()設置D3D的紋理採樣方式。
IDirect3DDevice9_SetTexture():Direct3D的API。用于設置當前啟用的紋理。
IDirect3DDevice9_SetPixelShader():Direct3D的API。用于設置使用的像素著色器。

IDirect3DDevice9_DrawPrimitiveUP():Direct3D的API,用于渲染。

上述幾個函數中,前3個函數是SDL中的函數,后3個函數是Direct3D的API。

在此附上前三個函數的代碼。

D3D_ActivateRenderer():激活渲染器。

static int D3D_ActivateRenderer(SDL_Renderer * renderer) {D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata;HRESULT result;if (data->updateSize) {SDL_Window *window = renderer->window;int w, h;SDL_GetWindowSize(window, &w, &h);data->pparams.BackBufferWidth = w;data->pparams.BackBufferHeight = h;if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {data->pparams.BackBufferFormat =PixelFormatToD3DFMT(SDL_GetWindowPixelFormat(window));} else {data->pparams.BackBufferFormat = D3DFMT_UNKNOWN;}if (D3D_Reset(renderer) < 0) {return -1;}data->updateSize = SDL_FALSE;}if (data->beginScene) {result = IDirect3DDevice9_BeginScene(data->device);if (result == D3DERR_DEVICELOST) {if (D3D_Reset(renderer) < 0) {return -1;}result = IDirect3DDevice9_BeginScene(data->device);}if (FAILED(result)) {return D3D_SetError("BeginScene()", result);}data->beginScene = SDL_FALSE;}return 0; }


D3D_SetBlendMode():設置渲染器狀態。

static void D3D_SetBlendMode(D3D_RenderData * data, int blendMode) {switch (blendMode) {case SDL_BLENDMODE_NONE:IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,FALSE);break;case SDL_BLENDMODE_BLEND:IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,TRUE);IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA);if (data->enableSeparateAlphaBlend) {IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,D3DBLEND_ONE);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,D3DBLEND_INVSRCALPHA);}break;case SDL_BLENDMODE_ADD:IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,TRUE);IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,D3DBLEND_ONE);if (data->enableSeparateAlphaBlend) {IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,D3DBLEND_ZERO);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,D3DBLEND_ONE);}break;case SDL_BLENDMODE_MOD:IDirect3DDevice9_SetRenderState(data->device, D3DRS_ALPHABLENDENABLE,TRUE);IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLEND,D3DBLEND_ZERO);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND,D3DBLEND_SRCCOLOR);if (data->enableSeparateAlphaBlend) {IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA,D3DBLEND_ZERO);IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA,D3DBLEND_ONE);}break;} }


D3D_UpdateTextureScaleMode():設置紋理採樣方式。

static void D3D_UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index) {if (texturedata->scaleMode != data->scaleMode[index]) {IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER,texturedata->scaleMode);IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER,texturedata->scaleMode);data->scaleMode[index] = texturedata->scaleMode;} }

2. OpenGL

OpenGL渲染器中相應RenderCopy()的函數是GL_RenderCopy(),它的源碼例如以下所看到的(位于render\opengl\SDL_render_gl.c)。

static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,const SDL_Rect * srcrect, const SDL_FRect * dstrect) {GL_RenderData *data = (GL_RenderData *) renderer->driverdata;GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;GLfloat minx, miny, maxx, maxy;GLfloat minu, maxu, minv, maxv;GL_ActivateRenderer(renderer);data->glEnable(texturedata->type);if (texturedata->yuv) {data->glActiveTextureARB(GL_TEXTURE2_ARB);data->glBindTexture(texturedata->type, texturedata->vtexture);data->glActiveTextureARB(GL_TEXTURE1_ARB);data->glBindTexture(texturedata->type, texturedata->utexture);data->glActiveTextureARB(GL_TEXTURE0_ARB);}data->glBindTexture(texturedata->type, texturedata->texture);if (texture->modMode) {GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);} else {GL_SetColor(data, 255, 255, 255, 255);}GL_SetBlendMode(data, texture->blendMode);if (texturedata->yuv) {GL_SetShader(data, SHADER_YV12);} else {GL_SetShader(data, SHADER_RGB);}minx = dstrect->x;miny = dstrect->y;maxx = dstrect->x + dstrect->w;maxy = dstrect->y + dstrect->h;minu = (GLfloat) srcrect->x / texture->w;minu *= texturedata->texw;maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;maxu *= texturedata->texw;minv = (GLfloat) srcrect->y / texture->h;minv *= texturedata->texh;maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;maxv *= texturedata->texh;data->glBegin(GL_TRIANGLE_STRIP);data->glTexCoord2f(minu, minv);data->glVertex2f(minx, miny);data->glTexCoord2f(maxu, minv);data->glVertex2f(maxx, miny);data->glTexCoord2f(minu, maxv);data->glVertex2f(minx, maxy);data->glTexCoord2f(maxu, maxv);data->glVertex2f(maxx, maxy);data->glEnd();data->glDisable(texturedata->type);return GL_CheckError("", renderer); }

從代碼中能夠看出。GL_RenderCopy()函數調用了OpenGL的API函數glActiveTexture(),glBindTexture()創建了一個紋理。而且使用GL_SetBlendMode(),GL_SetShader()設置了有關的一些參數。

有一點須要注意,在OpenGL渲染器中。假設輸入像素格式是YUV,就會使用3個紋理。

3. Software

Software渲染器中相應RenderCopy()的函數是SW_RenderCopy()。它的源碼例如以下所看到的(位于render\software\SDL_render_sw.c)。

static int SW_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,const SDL_Rect * srcrect, const SDL_FRect * dstrect) {SDL_Surface *surface = SW_ActivateRenderer(renderer);SDL_Surface *src = (SDL_Surface *) texture->driverdata;SDL_Rect final_rect;if (!surface) {return -1;}if (renderer->viewport.x || renderer->viewport.y) {final_rect.x = (int)(renderer->viewport.x + dstrect->x);final_rect.y = (int)(renderer->viewport.y + dstrect->y);} else {final_rect.x = (int)dstrect->x;final_rect.y = (int)dstrect->y;}final_rect.w = (int)dstrect->w;final_rect.h = (int)dstrect->h;if ( srcrect->w == final_rect.w && srcrect->h == final_rect.h ) {return SDL_BlitSurface(src, srcrect, surface, &final_rect);} else {return SDL_BlitScaled(src, srcrect, surface, &final_rect);} }

該函數的源碼還沒有具體分析。




轉載于:https://www.cnblogs.com/zfyouxi/p/5153044.html

總結

以上是生活随笔為你收集整理的SDL2源码分析6:拷贝到渲染器(SDL_RenderCopy())的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。