mirror of
				https://github.com/libsdl-org/SDL.git
				synced 2025-10-26 12:27:44 +00:00 
			
		
		
		
	Enable texture wrapping for SDL_RenderGeometry()
Currently wrapping is based on whether texture coordinates are outside of [0,1], but the code is structured so it's easy to add an API to set it and add additional wrapping modes if we want. Fixes https://github.com/libsdl-org/SDL/issues/9238 Closes https://github.com/libsdl-org/SDL/pull/5369
This commit is contained in:
		| @@ -576,6 +576,7 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren | |||||||
|             cmd->data.draw.color = *color; |             cmd->data.draw.color = *color; | ||||||
|             cmd->data.draw.blend = blendMode; |             cmd->data.draw.blend = blendMode; | ||||||
|             cmd->data.draw.texture = texture; |             cmd->data.draw.texture = texture; | ||||||
|  |             cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return cmd; |     return cmd; | ||||||
| @@ -715,12 +716,14 @@ static int QueueCmdGeometry(SDL_Renderer *renderer, SDL_Texture *texture, | |||||||
|                             const float *uv, int uv_stride, |                             const float *uv, int uv_stride, | ||||||
|                             int num_vertices, |                             int num_vertices, | ||||||
|                             const void *indices, int num_indices, int size_indices, |                             const void *indices, int num_indices, int size_indices, | ||||||
|                             float scale_x, float scale_y) |                             float scale_x, float scale_y, SDL_TextureAddressMode texture_address_mode) | ||||||
| { | { | ||||||
|     SDL_RenderCommand *cmd; |     SDL_RenderCommand *cmd; | ||||||
|     int retval = -1; |     int retval = -1; | ||||||
|     cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); |     cmd = PrepQueueCmdDraw(renderer, SDL_RENDERCMD_GEOMETRY, texture); | ||||||
|     if (cmd) { |     if (cmd) { | ||||||
|  |         cmd->data.draw.texture_address_mode = texture_address_mode; | ||||||
|  |  | ||||||
|         retval = renderer->QueueGeometry(renderer, cmd, texture, |         retval = renderer->QueueGeometry(renderer, cmd, texture, | ||||||
|                                          xy, xy_stride, |                                          xy, xy_stride, | ||||||
|                                          color, color_stride, uv, uv_stride, |                                          color, color_stride, uv, uv_stride, | ||||||
| @@ -3602,7 +3605,7 @@ int SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) | |||||||
|             retval = QueueCmdGeometry(renderer, NULL, |             retval = QueueCmdGeometry(renderer, NULL, | ||||||
|                                       xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0, |                                       xy, xy_stride, &renderer->color, 0 /* color_stride */, NULL, 0, | ||||||
|                                       num_vertices, indices, num_indices, size_indices, |                                       num_vertices, indices, num_indices, size_indices, | ||||||
|                                       1.0f, 1.0f); |                                       1.0f, 1.0f, SDL_TEXTURE_ADDRESS_CLAMP); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         SDL_small_free(xy, isstack1); |         SDL_small_free(xy, isstack1); | ||||||
| @@ -3818,7 +3821,7 @@ int SDL_RenderTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_FR | |||||||
|                                   num_vertices, |                                   num_vertices, | ||||||
|                                   indices, num_indices, size_indices, |                                   indices, num_indices, size_indices, | ||||||
|                                   renderer->view->scale.x, |                                   renderer->view->scale.x, | ||||||
|                                   renderer->view->scale.y); |                                   renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); | ||||||
|     } else { |     } else { | ||||||
|  |  | ||||||
|         real_dstrect.x *= renderer->view->scale.x; |         real_dstrect.x *= renderer->view->scale.x; | ||||||
| @@ -3976,7 +3979,7 @@ int SDL_RenderTextureRotated(SDL_Renderer *renderer, SDL_Texture *texture, | |||||||
|                                   num_vertices, |                                   num_vertices, | ||||||
|                                   indices, num_indices, size_indices, |                                   indices, num_indices, size_indices, | ||||||
|                                   renderer->view->scale.x, |                                   renderer->view->scale.x, | ||||||
|                                   renderer->view->scale.y); |                                   renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); | ||||||
|     } else { |     } else { | ||||||
|  |  | ||||||
|         retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, |         retval = QueueCmdCopyEx(renderer, texture, &real_srcrect, &real_dstrect, angle, &real_center, flip, | ||||||
| @@ -4340,7 +4343,7 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
|                                           xy, xy_stride, color, color_stride, uv, uv_stride, |                                           xy, xy_stride, color, color_stride, uv, uv_stride, | ||||||
|                                           num_vertices, prev, 3, 4, |                                           num_vertices, prev, 3, 4, | ||||||
|                                           renderer->view->scale.x, |                                           renderer->view->scale.x, | ||||||
|                                           renderer->view->scale.y); |                                           renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); | ||||||
|                 if (retval < 0) { |                 if (retval < 0) { | ||||||
|                     goto end; |                     goto end; | ||||||
|                 } |                 } | ||||||
| @@ -4361,7 +4364,7 @@ static int SDLCALL SDL_SW_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
|                                   xy, xy_stride, color, color_stride, uv, uv_stride, |                                   xy, xy_stride, color, color_stride, uv, uv_stride, | ||||||
|                                   num_vertices, prev, 3, 4, |                                   num_vertices, prev, 3, 4, | ||||||
|                                   renderer->view->scale.x, |                                   renderer->view->scale.x, | ||||||
|                                   renderer->view->scale.y); |                                   renderer->view->scale.y, SDL_TEXTURE_ADDRESS_CLAMP); | ||||||
|         if (retval < 0) { |         if (retval < 0) { | ||||||
|             goto end; |             goto end; | ||||||
|         } |         } | ||||||
| @@ -4386,6 +4389,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
|     int count = indices ? num_indices : num_vertices; |     int count = indices ? num_indices : num_vertices; | ||||||
|  |     SDL_TextureAddressMode texture_address_mode; | ||||||
|  |  | ||||||
|     CHECK_RENDERER_MAGIC(renderer, -1); |     CHECK_RENDERER_MAGIC(renderer, -1); | ||||||
|  |  | ||||||
| @@ -4440,13 +4444,16 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
|         texture = texture->native; |         texture = texture->native; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (texture) { |     texture_address_mode = renderer->texture_address_mode; | ||||||
|  |     if (texture_address_mode == SDL_TEXTURE_ADDRESS_AUTO && texture) { | ||||||
|  |         texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP; | ||||||
|         for (i = 0; i < num_vertices; ++i) { |         for (i = 0; i < num_vertices; ++i) { | ||||||
|             const float *uv_ = (const float *)((const char *)uv + i * uv_stride); |             const float *uv_ = (const float *)((const char *)uv + i * uv_stride); | ||||||
|             float u = uv_[0]; |             float u = uv_[0]; | ||||||
|             float v = uv_[1]; |             float v = uv_[1]; | ||||||
|             if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) { |             if (u < 0.0f || v < 0.0f || u > 1.0f || v > 1.0f) { | ||||||
|                 return SDL_SetError("Values of 'uv' out of bounds %f %f at %d/%d", u, v, i, num_vertices); |                 texture_address_mode = SDL_TEXTURE_ADDRESS_WRAP; | ||||||
|  |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -4473,7 +4480,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
|  |  | ||||||
|     /* For the software renderer, try to reinterpret triangles as SDL_Rect */ |     /* For the software renderer, try to reinterpret triangles as SDL_Rect */ | ||||||
| #if SDL_VIDEO_RENDER_SW | #if SDL_VIDEO_RENDER_SW | ||||||
|     if (renderer->software) { |     if (renderer->software && texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) { | ||||||
|         return SDL_SW_RenderGeometryRaw(renderer, texture, |         return SDL_SW_RenderGeometryRaw(renderer, texture, | ||||||
|                                         xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, |                                         xy, xy_stride, color, color_stride, uv, uv_stride, num_vertices, | ||||||
|                                         indices, num_indices, size_indices); |                                         indices, num_indices, size_indices); | ||||||
| @@ -4485,7 +4492,7 @@ int SDL_RenderGeometryRaw(SDL_Renderer *renderer, | |||||||
|                               num_vertices, |                               num_vertices, | ||||||
|                               indices, num_indices, size_indices, |                               indices, num_indices, size_indices, | ||||||
|                               renderer->view->scale.x, |                               renderer->view->scale.x, | ||||||
|                               renderer->view->scale.y); |                               renderer->view->scale.y, texture_address_mode); | ||||||
| } | } | ||||||
|  |  | ||||||
| SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) | SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) | ||||||
|   | |||||||
| @@ -30,6 +30,13 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | typedef enum SDL_TextureAddressMode | ||||||
|  | { | ||||||
|  |     SDL_TEXTURE_ADDRESS_AUTO, | ||||||
|  |     SDL_TEXTURE_ADDRESS_CLAMP, | ||||||
|  |     SDL_TEXTURE_ADDRESS_WRAP, | ||||||
|  | } SDL_TextureAddressMode; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * A rectangle, with the origin at the upper left (double precision). |  * A rectangle, with the origin at the upper left (double precision). | ||||||
|  */ |  */ | ||||||
| @@ -132,6 +139,7 @@ typedef struct SDL_RenderCommand | |||||||
|             SDL_FColor color; |             SDL_FColor color; | ||||||
|             SDL_BlendMode blend; |             SDL_BlendMode blend; | ||||||
|             SDL_Texture *texture; |             SDL_Texture *texture; | ||||||
|  |             SDL_TextureAddressMode texture_address_mode; | ||||||
|         } draw; |         } draw; | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
| @@ -262,6 +270,7 @@ struct SDL_Renderer | |||||||
|     float color_scale; |     float color_scale; | ||||||
|     SDL_FColor color;        /**< Color for drawing operations values */ |     SDL_FColor color;        /**< Color for drawing operations values */ | ||||||
|     SDL_BlendMode blendMode; /**< The drawing blend mode */ |     SDL_BlendMode blendMode; /**< The drawing blend mode */ | ||||||
|  |     SDL_TextureAddressMode texture_address_mode; | ||||||
|  |  | ||||||
|     SDL_RenderCommand *render_commands; |     SDL_RenderCommand *render_commands; | ||||||
|     SDL_RenderCommand *render_commands_tail; |     SDL_RenderCommand *render_commands_tail; | ||||||
|   | |||||||
| @@ -62,7 +62,8 @@ typedef struct | |||||||
|     SDL_bool updateSize; |     SDL_bool updateSize; | ||||||
|     SDL_bool beginScene; |     SDL_bool beginScene; | ||||||
|     SDL_bool enableSeparateAlphaBlend; |     SDL_bool enableSeparateAlphaBlend; | ||||||
|     D3DTEXTUREFILTERTYPE scaleMode[8]; |     D3DTEXTUREFILTERTYPE scaleMode[3]; | ||||||
|  |     SDL_TextureAddressMode addressMode[3]; | ||||||
|     IDirect3DSurface9 *defaultRenderTarget; |     IDirect3DSurface9 *defaultRenderTarget; | ||||||
|     IDirect3DSurface9 *currentRenderTarget; |     IDirect3DSurface9 *currentRenderTarget; | ||||||
|     void *d3dxDLL; |     void *d3dxDLL; | ||||||
| @@ -277,6 +278,9 @@ static void D3D_InitRenderState(D3D_RenderData *data) | |||||||
|     /* Reset our current scale mode */ |     /* Reset our current scale mode */ | ||||||
|     SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode)); |     SDL_memset(data->scaleMode, 0xFF, sizeof(data->scaleMode)); | ||||||
|  |  | ||||||
|  |     /* Reset our current address mode */ | ||||||
|  |     SDL_zeroa(data->addressMode); | ||||||
|  |  | ||||||
|     /* Start the render with beginScene */ |     /* Start the render with beginScene */ | ||||||
|     data->beginScene = SDL_TRUE; |     data->beginScene = SDL_TRUE; | ||||||
| } | } | ||||||
| @@ -927,19 +931,32 @@ static int BindTextureRep(IDirect3DDevice9 *device, D3D_TextureRep *texture, DWO | |||||||
| static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index) | static void UpdateTextureScaleMode(D3D_RenderData *data, D3D_TextureData *texturedata, unsigned index) | ||||||
| { | { | ||||||
|     if (texturedata->scaleMode != data->scaleMode[index]) { |     if (texturedata->scaleMode != data->scaleMode[index]) { | ||||||
|         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, |         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, texturedata->scaleMode); | ||||||
|                                          texturedata->scaleMode); |         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, texturedata->scaleMode); | ||||||
|         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, |  | ||||||
|                                          texturedata->scaleMode); |  | ||||||
|         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, |  | ||||||
|                                          D3DTADDRESS_CLAMP); |  | ||||||
|         IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, |  | ||||||
|                                          D3DTADDRESS_CLAMP); |  | ||||||
|         data->scaleMode[index] = texturedata->scaleMode; |         data->scaleMode[index] = texturedata->scaleMode; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Shader *shader, const float **shader_params) | static void UpdateTextureAddressMode(D3D_RenderData *data, SDL_TextureAddressMode addressMode, unsigned index) | ||||||
|  | { | ||||||
|  |     if (addressMode != data->addressMode[index]) { | ||||||
|  |         switch (addressMode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); | ||||||
|  |             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); | ||||||
|  |             IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         data->addressMode[index] = addressMode; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, SDL_TextureAddressMode addressMode, D3D9_Shader *shader, const float **shader_params) | ||||||
| { | { | ||||||
|     D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal; |     D3D_TextureData *texturedata = (D3D_TextureData *)texture->internal; | ||||||
|  |  | ||||||
| @@ -948,6 +965,7 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Sh | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     UpdateTextureScaleMode(data, texturedata, 0); |     UpdateTextureScaleMode(data, texturedata, 0); | ||||||
|  |     UpdateTextureAddressMode(data, addressMode, 0); | ||||||
|  |  | ||||||
|     *shader = texturedata->shader; |     *shader = texturedata->shader; | ||||||
|     *shader_params = texturedata->shader_params; |     *shader_params = texturedata->shader_params; | ||||||
| @@ -959,6 +977,8 @@ static int SetupTextureState(D3D_RenderData *data, SDL_Texture *texture, D3D9_Sh | |||||||
|     if (texturedata->yuv) { |     if (texturedata->yuv) { | ||||||
|         UpdateTextureScaleMode(data, texturedata, 1); |         UpdateTextureScaleMode(data, texturedata, 1); | ||||||
|         UpdateTextureScaleMode(data, texturedata, 2); |         UpdateTextureScaleMode(data, texturedata, 2); | ||||||
|  |         UpdateTextureAddressMode(data, addressMode, 1); | ||||||
|  |         UpdateTextureAddressMode(data, addressMode, 2); | ||||||
|  |  | ||||||
|         if (BindTextureRep(data->device, &texturedata->utexture, 1) < 0) { |         if (BindTextureRep(data->device, &texturedata->utexture, 1) < 0) { | ||||||
|             return -1; |             return -1; | ||||||
| @@ -994,7 +1014,7 @@ static int SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) | |||||||
|             IDirect3DDevice9_SetTexture(data->device, 2, NULL); |             IDirect3DDevice9_SetTexture(data->device, 2, NULL); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         if (texture && SetupTextureState(data, texture, &shader, &shader_params) < 0) { |         if (texture && SetupTextureState(data, texture, cmd->data.draw.texture_address_mode, &shader, &shader_params) < 0) { | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,6 +68,16 @@ extern ISwapChainBackgroundPanelNative *WINRT_GlobalSwapChainBackgroundPanelNati | |||||||
| /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when | /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when | ||||||
|    !!! FIXME:  textures are needed. */ |    !!! FIXME:  textures are needed. */ | ||||||
|  |  | ||||||
|  | /* Sampler types */ | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |     SDL_D3D11_SAMPLER_NEAREST_CLAMP, | ||||||
|  |     SDL_D3D11_SAMPLER_NEAREST_WRAP, | ||||||
|  |     SDL_D3D11_SAMPLER_LINEAR_CLAMP, | ||||||
|  |     SDL_D3D11_SAMPLER_LINEAR_WRAP, | ||||||
|  |     SDL_NUM_D3D11_SAMPLERS | ||||||
|  | } SDL_D3D11_sampler_type; | ||||||
|  |  | ||||||
| /* Vertex shader, common values */ | /* Vertex shader, common values */ | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| @@ -181,8 +191,7 @@ typedef struct | |||||||
|     ID3D11PixelShader *pixelShaders[NUM_SHADERS]; |     ID3D11PixelShader *pixelShaders[NUM_SHADERS]; | ||||||
|     int blendModesCount; |     int blendModesCount; | ||||||
|     D3D11_BlendMode *blendModes; |     D3D11_BlendMode *blendModes; | ||||||
|     ID3D11SamplerState *nearestPixelSampler; |     ID3D11SamplerState *samplers[SDL_NUM_D3D11_SAMPLERS]; | ||||||
|     ID3D11SamplerState *linearSampler; |  | ||||||
|     D3D_FEATURE_LEVEL featureLevel; |     D3D_FEATURE_LEVEL featureLevel; | ||||||
|     SDL_bool pixelSizeChanged; |     SDL_bool pixelSizeChanged; | ||||||
|  |  | ||||||
| @@ -346,8 +355,9 @@ static void D3D11_ReleaseAll(SDL_Renderer *renderer) | |||||||
|         SAFE_RELEASE(data->vertexShaderConstants); |         SAFE_RELEASE(data->vertexShaderConstants); | ||||||
|         SAFE_RELEASE(data->clippedRasterizer); |         SAFE_RELEASE(data->clippedRasterizer); | ||||||
|         SAFE_RELEASE(data->mainRasterizer); |         SAFE_RELEASE(data->mainRasterizer); | ||||||
|         SAFE_RELEASE(data->linearSampler); |         for (i = 0; i < SDL_arraysize(data->samplers); ++i) { | ||||||
|         SAFE_RELEASE(data->nearestPixelSampler); |             SAFE_RELEASE(data->samplers[i]); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (data->blendModesCount > 0) { |         if (data->blendModesCount > 0) { | ||||||
|             for (i = 0; i < data->blendModesCount; ++i) { |             for (i = 0; i < data->blendModesCount; ++i) { | ||||||
| @@ -734,31 +744,35 @@ static HRESULT D3D11_CreateDeviceResources(SDL_Renderer *renderer) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Create samplers to use when drawing textures: */ |     /* Create samplers to use when drawing textures: */ | ||||||
|  |     static struct  | ||||||
|  |     { | ||||||
|  |         D3D11_FILTER filter; | ||||||
|  |         D3D11_TEXTURE_ADDRESS_MODE address; | ||||||
|  |     } samplerParams[] = { | ||||||
|  |         { D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_CLAMP }, | ||||||
|  |         { D3D11_FILTER_MIN_MAG_MIP_POINT, D3D11_TEXTURE_ADDRESS_WRAP }, | ||||||
|  |         { D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_CLAMP }, | ||||||
|  |         { D3D11_FILTER_MIN_MAG_MIP_LINEAR, D3D11_TEXTURE_ADDRESS_WRAP }, | ||||||
|  |     }; | ||||||
|  |     SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_D3D11_SAMPLERS); | ||||||
|     SDL_zero(samplerDesc); |     SDL_zero(samplerDesc); | ||||||
|     samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; |  | ||||||
|     samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; |  | ||||||
|     samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; |  | ||||||
|     samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; |     samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; | ||||||
|     samplerDesc.MipLODBias = 0.0f; |     samplerDesc.MipLODBias = 0.0f; | ||||||
|     samplerDesc.MaxAnisotropy = 1; |     samplerDesc.MaxAnisotropy = 1; | ||||||
|     samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; |     samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; | ||||||
|     samplerDesc.MinLOD = 0.0f; |     samplerDesc.MinLOD = 0.0f; | ||||||
|     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; |     samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; | ||||||
|     result = ID3D11Device_CreateSamplerState(data->d3dDevice, |     for (int i = 0; i < SDL_arraysize(samplerParams); ++i) { | ||||||
|                                              &samplerDesc, |         samplerDesc.Filter = samplerParams[i].filter; | ||||||
|                                              &data->nearestPixelSampler); |         samplerDesc.AddressU = samplerParams[i].address; | ||||||
|     if (FAILED(result)) { |         samplerDesc.AddressV = samplerParams[i].address; | ||||||
|         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result); |         result = ID3D11Device_CreateSamplerState(data->d3dDevice, | ||||||
|         goto done; |                                                  &samplerDesc, | ||||||
|     } |                                                  &data->samplers[i]); | ||||||
|  |         if (FAILED(result)) { | ||||||
|     samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; |             WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result); | ||||||
|     result = ID3D11Device_CreateSamplerState(data->d3dDevice, |             goto done; | ||||||
|                                              &samplerDesc, |         } | ||||||
|                                              &data->linearSampler); |  | ||||||
|     if (FAILED(result)) { |  | ||||||
|         WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [linear filter]"), result); |  | ||||||
|         goto done; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Setup Direct3D rasterizer states */ |     /* Setup Direct3D rasterizer states */ | ||||||
| @@ -2426,10 +2440,28 @@ static int D3D11_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c | |||||||
|  |  | ||||||
|     switch (textureData->scaleMode) { |     switch (textureData->scaleMode) { | ||||||
|     case D3D11_FILTER_MIN_MAG_MIP_POINT: |     case D3D11_FILTER_MIN_MAG_MIP_POINT: | ||||||
|         textureSampler = rendererData->nearestPixelSampler; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_NEAREST_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_NEAREST_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case D3D11_FILTER_MIN_MAG_MIP_LINEAR: |     case D3D11_FILTER_MIN_MAG_MIP_LINEAR: | ||||||
|         textureSampler = rendererData->linearSampler; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_LINEAR_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_D3D11_SAMPLER_LINEAR_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode); |         return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode); | ||||||
|   | |||||||
| @@ -134,6 +134,16 @@ extern "C" { | |||||||
| /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when | /* !!! FIXME: vertex buffer bandwidth could be lower; only use UV coords when | ||||||
|    !!! FIXME:  textures are needed. */ |    !!! FIXME:  textures are needed. */ | ||||||
|  |  | ||||||
|  | /* Sampler types */ | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |     SDL_D3D12_SAMPLER_NEAREST_CLAMP, | ||||||
|  |     SDL_D3D12_SAMPLER_NEAREST_WRAP, | ||||||
|  |     SDL_D3D12_SAMPLER_LINEAR_CLAMP, | ||||||
|  |     SDL_D3D12_SAMPLER_LINEAR_WRAP, | ||||||
|  |     SDL_D3D12_NUM_SAMPLERS | ||||||
|  | } SDL_D3D12_sampler_type; | ||||||
|  |  | ||||||
| /* Vertex shader, common values */ | /* Vertex shader, common values */ | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| @@ -294,8 +304,7 @@ typedef struct | |||||||
|     D3D12_PipelineState *currentPipelineState; |     D3D12_PipelineState *currentPipelineState; | ||||||
|  |  | ||||||
|     D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS]; |     D3D12_VertexBuffer vertexBuffers[SDL_D3D12_NUM_VERTEX_BUFFERS]; | ||||||
|     D3D12_CPU_DESCRIPTOR_HANDLE nearestPixelSampler; |     D3D12_CPU_DESCRIPTOR_HANDLE samplers[SDL_D3D12_NUM_SAMPLERS]; | ||||||
|     D3D12_CPU_DESCRIPTOR_HANDLE linearSampler; |  | ||||||
|  |  | ||||||
|     /* Data for staging/allocating textures */ |     /* Data for staging/allocating textures */ | ||||||
|     ID3D12Resource *uploadBuffers[SDL_D3D12_NUM_UPLOAD_BUFFERS]; |     ID3D12Resource *uploadBuffers[SDL_D3D12_NUM_UPLOAD_BUFFERS]; | ||||||
| @@ -1057,7 +1066,7 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) | |||||||
|     data->srvDescriptorSize = D3D_CALL(d3dDevice, GetDescriptorHandleIncrementSize, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); |     data->srvDescriptorSize = D3D_CALL(d3dDevice, GetDescriptorHandleIncrementSize, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); | ||||||
|  |  | ||||||
|     SDL_zero(descriptorHeapDesc); |     SDL_zero(descriptorHeapDesc); | ||||||
|     descriptorHeapDesc.NumDescriptors = 2; |     descriptorHeapDesc.NumDescriptors = 4; | ||||||
|     descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; |     descriptorHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; | ||||||
|     descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; |     descriptorHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; | ||||||
|     result = D3D_CALL(data->d3dDevice, CreateDescriptorHeap, |     result = D3D_CALL(data->d3dDevice, CreateDescriptorHeap, | ||||||
| @@ -1165,22 +1174,32 @@ static HRESULT D3D12_CreateDeviceResources(SDL_Renderer *renderer) | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /* Create samplers to use when drawing textures: */ |     /* Create samplers to use when drawing textures: */ | ||||||
|  |     static struct | ||||||
|  |     { | ||||||
|  |         D3D12_FILTER filter; | ||||||
|  |         D3D12_TEXTURE_ADDRESS_MODE address; | ||||||
|  |     } samplerParams[] = { | ||||||
|  |         { D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_CLAMP }, | ||||||
|  |         { D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_WRAP }, | ||||||
|  |         { D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP }, | ||||||
|  |         { D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_WRAP }, | ||||||
|  |     }; | ||||||
|  |     SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_D3D12_NUM_SAMPLERS); | ||||||
|     SDL_zero(samplerDesc); |     SDL_zero(samplerDesc); | ||||||
|     samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; |  | ||||||
|     samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; |  | ||||||
|     samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; |  | ||||||
|     samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; |     samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; | ||||||
|     samplerDesc.MipLODBias = 0.0f; |     samplerDesc.MipLODBias = 0.0f; | ||||||
|     samplerDesc.MaxAnisotropy = 1; |     samplerDesc.MaxAnisotropy = 1; | ||||||
|     samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; |     samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; | ||||||
|     samplerDesc.MinLOD = 0.0f; |     samplerDesc.MinLOD = 0.0f; | ||||||
|     samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; |     samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; | ||||||
|     D3D_CALL_RET_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(data->samplerDescriptorHeap, &data->nearestPixelSampler); |     D3D_CALL_RET_ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(data->samplerDescriptorHeap, &data->samplers[0]); | ||||||
|     D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->nearestPixelSampler); |     for (i = 0; i < SDL_arraysize(samplerParams); ++i) { | ||||||
|  |         samplerDesc.Filter = samplerParams[i].filter; | ||||||
|     samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; |         samplerDesc.AddressU = samplerParams[i].address; | ||||||
|     data->linearSampler.ptr = data->nearestPixelSampler.ptr + data->samplerDescriptorSize; |         samplerDesc.AddressV = samplerParams[i].address; | ||||||
|     D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->linearSampler); |         data->samplers[i].ptr = data->samplers[0].ptr + i * data->samplerDescriptorSize; | ||||||
|  |         D3D_CALL(data->d3dDevice, CreateSampler, &samplerDesc, data->samplers[i]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* Initialize the pool allocator for SRVs */ |     /* Initialize the pool allocator for SRVs */ | ||||||
|     for (i = 0; i < SDL_D3D12_MAX_NUM_TEXTURES; ++i) { |     for (i = 0; i < SDL_D3D12_MAX_NUM_TEXTURES; ++i) { | ||||||
| @@ -2797,10 +2816,28 @@ static int D3D12_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *c | |||||||
|  |  | ||||||
|     switch (textureData->scaleMode) { |     switch (textureData->scaleMode) { | ||||||
|     case D3D12_FILTER_MIN_MAG_MIP_POINT: |     case D3D12_FILTER_MIN_MAG_MIP_POINT: | ||||||
|         textureSampler = &rendererData->nearestPixelSampler; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_NEAREST_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_NEAREST_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case D3D12_FILTER_MIN_MAG_MIP_LINEAR: |     case D3D12_FILTER_MIN_MAG_MIP_LINEAR: | ||||||
|         textureSampler = &rendererData->linearSampler; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_LINEAR_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = &rendererData->samplers[SDL_D3D12_SAMPLER_LINEAR_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode); |         return SDL_SetError("Unknown scale mode: %d\n", textureData->scaleMode); | ||||||
|   | |||||||
| @@ -80,6 +80,16 @@ static const size_t CONSTANTS_OFFSET_DECODE_BT2020_LIMITED = ALIGN_CONSTANTS(16, | |||||||
| static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4); | static const size_t CONSTANTS_OFFSET_DECODE_BT2020_FULL = ALIGN_CONSTANTS(16, CONSTANTS_OFFSET_DECODE_BT2020_LIMITED + sizeof(float) * 4 * 4); | ||||||
| static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4; | static const size_t CONSTANTS_LENGTH = CONSTANTS_OFFSET_DECODE_BT2020_FULL + sizeof(float) * 4 * 4; | ||||||
|  |  | ||||||
|  | /* Sampler types */ | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |     SDL_METAL_SAMPLER_NEAREST_CLAMP, | ||||||
|  |     SDL_METAL_SAMPLER_NEAREST_WRAP, | ||||||
|  |     SDL_METAL_SAMPLER_LINEAR_CLAMP, | ||||||
|  |     SDL_METAL_SAMPLER_LINEAR_WRAP, | ||||||
|  |     SDL_NUM_METAL_SAMPLERS | ||||||
|  | } SDL_METAL_sampler_type; | ||||||
|  |  | ||||||
| typedef enum SDL_MetalVertexFunction | typedef enum SDL_MetalVertexFunction | ||||||
| { | { | ||||||
|     SDL_METAL_VERTEX_SOLID, |     SDL_METAL_VERTEX_SOLID, | ||||||
| @@ -130,8 +140,7 @@ typedef struct METAL_ShaderPipelines | |||||||
| @property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder; | @property(nonatomic, retain) id<MTLRenderCommandEncoder> mtlcmdencoder; | ||||||
| @property(nonatomic, retain) id<MTLLibrary> mtllibrary; | @property(nonatomic, retain) id<MTLLibrary> mtllibrary; | ||||||
| @property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer; | @property(nonatomic, retain) id<CAMetalDrawable> mtlbackbuffer; | ||||||
| @property(nonatomic, retain) id<MTLSamplerState> mtlsamplernearest; | @property(nonatomic, retain) NSMutableArray<id<MTLSamplerState>> *mtlsamplers; | ||||||
| @property(nonatomic, retain) id<MTLSamplerState> mtlsamplerlinear; |  | ||||||
| @property(nonatomic, retain) id<MTLBuffer> mtlbufconstants; | @property(nonatomic, retain) id<MTLBuffer> mtlbufconstants; | ||||||
| @property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices; | @property(nonatomic, retain) id<MTLBuffer> mtlbufquadindices; | ||||||
| @property(nonatomic, assign) SDL_MetalView mtlview; | @property(nonatomic, assign) SDL_MetalView mtlview; | ||||||
| @@ -148,7 +157,6 @@ typedef struct METAL_ShaderPipelines | |||||||
| @interface METAL_TextureData : NSObject | @interface METAL_TextureData : NSObject | ||||||
| @property(nonatomic, retain) id<MTLTexture> mtltexture; | @property(nonatomic, retain) id<MTLTexture> mtltexture; | ||||||
| @property(nonatomic, retain) id<MTLTexture> mtltextureUv; | @property(nonatomic, retain) id<MTLTexture> mtltextureUv; | ||||||
| @property(nonatomic, retain) id<MTLSamplerState> mtlsampler; |  | ||||||
| @property(nonatomic, assign) SDL_MetalFragmentFunction fragmentFunction; | @property(nonatomic, assign) SDL_MetalFragmentFunction fragmentFunction; | ||||||
| #if SDL_HAVE_YUV | #if SDL_HAVE_YUV | ||||||
| @property(nonatomic, assign) BOOL yuv; | @property(nonatomic, assign) BOOL yuv; | ||||||
| @@ -739,11 +747,6 @@ static int METAL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL | |||||||
|         } |         } | ||||||
| #endif /* SDL_HAVE_YUV */ | #endif /* SDL_HAVE_YUV */ | ||||||
|         texturedata = [[METAL_TextureData alloc] init]; |         texturedata = [[METAL_TextureData alloc] init]; | ||||||
|         if (texture->scaleMode == SDL_SCALEMODE_NEAREST) { |  | ||||||
|             texturedata.mtlsampler = data.mtlsamplernearest; |  | ||||||
|         } else { |  | ||||||
|             texturedata.mtlsampler = data.mtlsamplerlinear; |  | ||||||
|         } |  | ||||||
|         if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_SRGB) { |         if (SDL_COLORSPACETRANSFER(texture->colorspace) == SDL_TRANSFER_CHARACTERISTICS_SRGB) { | ||||||
|             texturedata.fragmentFunction = SDL_METAL_FRAGMENT_COPY; |             texturedata.fragmentFunction = SDL_METAL_FRAGMENT_COPY; | ||||||
| #if SDL_HAVE_YUV | #if SDL_HAVE_YUV | ||||||
| @@ -1094,16 +1097,6 @@ static void METAL_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) | |||||||
|  |  | ||||||
| static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) | static void METAL_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode) | ||||||
| { | { | ||||||
|     @autoreleasepool { |  | ||||||
|         METAL_RenderData *data = (__bridge METAL_RenderData *)renderer->internal; |  | ||||||
|         METAL_TextureData *texturedata = (__bridge METAL_TextureData *)texture->internal; |  | ||||||
|  |  | ||||||
|         if (scaleMode == SDL_SCALEMODE_NEAREST) { |  | ||||||
|             texturedata.mtlsampler = data.mtlsamplernearest; |  | ||||||
|         } else { |  | ||||||
|             texturedata.mtlsampler = data.mtlsamplerlinear; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) | static int METAL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture) | ||||||
| @@ -1503,13 +1496,32 @@ static SDL_bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cm | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (texture != statecache->texture) { |     if (texture != statecache->texture) { | ||||||
|         METAL_TextureData *oldtexturedata = NULL; |         id<MTLSamplerState> mtlsampler; | ||||||
|         if (statecache->texture) { |  | ||||||
|             oldtexturedata = (__bridge METAL_TextureData *)statecache->texture->internal; |         if (texture->scaleMode == SDL_SCALEMODE_NEAREST) { | ||||||
|         } |             switch (cmd->data.draw.texture_address_mode) { | ||||||
|         if (!oldtexturedata || (texturedata.mtlsampler != oldtexturedata.mtlsampler)) { |             case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|             [data.mtlcmdencoder setFragmentSamplerState:texturedata.mtlsampler atIndex:0]; |                 mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_CLAMP]; | ||||||
|  |                 break; | ||||||
|  |             case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |                 mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_NEAREST_WRAP]; | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |             case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |                 mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_CLAMP]; | ||||||
|  |                 break; | ||||||
|  |             case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |                 mtlsampler = data.mtlsamplers[SDL_METAL_SAMPLER_LINEAR_WRAP]; | ||||||
|  |                 break; | ||||||
|  |             default: | ||||||
|  |                 return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |         [data.mtlcmdencoder setFragmentSamplerState:mtlsampler atIndex:0]; | ||||||
|  |  | ||||||
|         [data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0]; |         [data.mtlcmdencoder setFragmentTexture:texturedata.mtltexture atIndex:0]; | ||||||
| #if SDL_HAVE_YUV | #if SDL_HAVE_YUV | ||||||
| @@ -1904,7 +1916,6 @@ static int METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_ | |||||||
|         MTLSamplerDescriptor *samplerdesc; |         MTLSamplerDescriptor *samplerdesc; | ||||||
|         id<MTLCommandQueue> mtlcmdqueue; |         id<MTLCommandQueue> mtlcmdqueue; | ||||||
|         id<MTLLibrary> mtllibrary; |         id<MTLLibrary> mtllibrary; | ||||||
|         id<MTLSamplerState> mtlsamplernearest, mtlsamplerlinear; |  | ||||||
|         id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices; |         id<MTLBuffer> mtlbufconstantstaging, mtlbufquadindicesstaging, mtlbufconstants, mtlbufquadindices; | ||||||
|         id<MTLCommandBuffer> cmdbuffer; |         id<MTLCommandBuffer> cmdbuffer; | ||||||
|         id<MTLBlitCommandEncoder> blitcmd; |         id<MTLBlitCommandEncoder> blitcmd; | ||||||
| @@ -2066,17 +2077,27 @@ static int METAL_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_ | |||||||
|         data.allpipelines = NULL; |         data.allpipelines = NULL; | ||||||
|         ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm); |         ChooseShaderPipelines(data, MTLPixelFormatBGRA8Unorm); | ||||||
|  |  | ||||||
|  |         static struct | ||||||
|  |         { | ||||||
|  |             MTLSamplerMinMagFilter filter; | ||||||
|  |             MTLSamplerAddressMode address; | ||||||
|  |         } samplerParams[] = { | ||||||
|  |             { MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeClampToEdge }, | ||||||
|  |             { MTLSamplerMinMagFilterNearest, MTLSamplerAddressModeRepeat }, | ||||||
|  |             { MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeClampToEdge }, | ||||||
|  |             { MTLSamplerMinMagFilterLinear, MTLSamplerAddressModeRepeat }, | ||||||
|  |         }; | ||||||
|  |         SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_NUM_METAL_SAMPLERS); | ||||||
|  |  | ||||||
|  |         data.mtlsamplers = [[NSMutableArray<id<MTLSamplerState>> alloc] init]; | ||||||
|         samplerdesc = [[MTLSamplerDescriptor alloc] init]; |         samplerdesc = [[MTLSamplerDescriptor alloc] init]; | ||||||
|  |         for (int i = 0; i < SDL_arraysize(samplerParams); ++i) { | ||||||
|         samplerdesc.minFilter = MTLSamplerMinMagFilterNearest; |             samplerdesc.minFilter = samplerParams[i].filter; | ||||||
|         samplerdesc.magFilter = MTLSamplerMinMagFilterNearest; |             samplerdesc.magFilter = samplerParams[i].filter; | ||||||
|         mtlsamplernearest = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc]; |             samplerdesc.sAddressMode = samplerParams[i].address; | ||||||
|         data.mtlsamplernearest = mtlsamplernearest; |             samplerdesc.tAddressMode = samplerParams[i].address; | ||||||
|  |             [data.mtlsamplers addObject:[data.mtldevice newSamplerStateWithDescriptor:samplerdesc]]; | ||||||
|         samplerdesc.minFilter = MTLSamplerMinMagFilterLinear; |         } | ||||||
|         samplerdesc.magFilter = MTLSamplerMinMagFilterLinear; |  | ||||||
|         mtlsamplerlinear = [data.mtldevice newSamplerStateWithDescriptor:samplerdesc]; |  | ||||||
|         data.mtlsamplerlinear = mtlsamplerlinear; |  | ||||||
|  |  | ||||||
|         mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared]; |         mtlbufconstantstaging = [data.mtldevice newBufferWithLength:CONSTANTS_LENGTH options:MTLResourceStorageModeShared]; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -541,15 +541,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr | |||||||
|     renderdata->glBindTexture(textype, data->texture); |     renderdata->glBindTexture(textype, data->texture); | ||||||
|     renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode); |     renderdata->glTexParameteri(textype, GL_TEXTURE_MIN_FILTER, scaleMode); | ||||||
|     renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, scaleMode); |     renderdata->glTexParameteri(textype, 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 (textype != GL_TEXTURE_RECTANGLE_ARB) { |  | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|     } |  | ||||||
| #ifdef SDL_PLATFORM_MACOS | #ifdef SDL_PLATFORM_MACOS | ||||||
| #ifndef GL_TEXTURE_STORAGE_HINT_APPLE | #ifndef GL_TEXTURE_STORAGE_HINT_APPLE | ||||||
| #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC | #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC | ||||||
| @@ -609,10 +600,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr | |||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, |         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, | ||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, |         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, | ||||||
|                                  (texture_h + 1) / 2, 0, format, type, NULL); |                                  (texture_h + 1) / 2, 0, format, type, NULL); | ||||||
|         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture); |         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER, data->utexture); | ||||||
| @@ -622,10 +609,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr | |||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, |         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, | ||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, |         renderdata->glTexImage2D(textype, 0, internalFormat, (texture_w + 1) / 2, | ||||||
|                                  (texture_h + 1) / 2, 0, format, type, NULL); |                                  (texture_h + 1) / 2, 0, format, type, NULL); | ||||||
|         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture); |         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER, data->vtexture); | ||||||
| @@ -646,10 +629,6 @@ static int GL_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_Pr | |||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, |         renderdata->glTexParameteri(textype, GL_TEXTURE_MAG_FILTER, | ||||||
|                                     scaleMode); |                                     scaleMode); | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_S, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(textype, GL_TEXTURE_WRAP_T, |  | ||||||
|                                     GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2, |         renderdata->glTexImage2D(textype, 0, GL_LUMINANCE_ALPHA, (texture_w + 1) / 2, | ||||||
|                                  (texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); |                                  (texture_h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); | ||||||
|         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture); |         SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER, data->utexture); | ||||||
| @@ -1141,6 +1120,23 @@ static int SetDrawState(GL_RenderData *data, const SDL_RenderCommand *cmd, const | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int SetTextureAddressMode(GL_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode) | ||||||
|  | { | ||||||
|  |     switch (addressMode) { | ||||||
|  |     case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||||
|  |         break; | ||||||
|  |     case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT); | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         return SDL_SetError("Unknown texture address mode: %d\n", addressMode); | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) | static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) | ||||||
| { | { | ||||||
|     SDL_Texture *texture = cmd->data.draw.texture; |     SDL_Texture *texture = cmd->data.draw.texture; | ||||||
| @@ -1157,16 +1153,28 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) | |||||||
|             } |             } | ||||||
|             data->glBindTexture(textype, texturedata->vtexture); |             data->glBindTexture(textype, texturedata->vtexture); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             if (data->GL_ARB_multitexture_supported) { |             if (data->GL_ARB_multitexture_supported) { | ||||||
|                 data->glActiveTextureARB(GL_TEXTURE1_ARB); |                 data->glActiveTextureARB(GL_TEXTURE1_ARB); | ||||||
|             } |             } | ||||||
|             data->glBindTexture(textype, texturedata->utexture); |             data->glBindTexture(textype, texturedata->utexture); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         if (texturedata->nv12) { |         if (texturedata->nv12) { | ||||||
|             if (data->GL_ARB_multitexture_supported) { |             if (data->GL_ARB_multitexture_supported) { | ||||||
|                 data->glActiveTextureARB(GL_TEXTURE1_ARB); |                 data->glActiveTextureARB(GL_TEXTURE1_ARB); | ||||||
|             } |             } | ||||||
|             data->glBindTexture(textype, texturedata->utexture); |             data->glBindTexture(textype, texturedata->utexture); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         if (data->GL_ARB_multitexture_supported) { |         if (data->GL_ARB_multitexture_supported) { | ||||||
| @@ -1174,6 +1182,10 @@ static int SetCopyState(GL_RenderData *data, const SDL_RenderCommand *cmd) | |||||||
|         } |         } | ||||||
|         data->glBindTexture(textype, texturedata->texture); |         data->glBindTexture(textype, texturedata->texture); | ||||||
|  |  | ||||||
|  |         if (SetTextureAddressMode(data, textype, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         data->drawstate.texture = texture; |         data->drawstate.texture = texture; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1030,6 +1030,23 @@ static int SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, co | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode) | ||||||
|  | { | ||||||
|  |     switch (addressMode) { | ||||||
|  |     case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||||
|  |         break; | ||||||
|  |     case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT); | ||||||
|  |         data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT); | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         return SDL_SetError("Unknown texture address mode: %d\n", addressMode); | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices) | static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices) | ||||||
| { | { | ||||||
|     GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal; |     GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal; | ||||||
| @@ -1162,18 +1179,35 @@ static int SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, vo | |||||||
|             data->glActiveTexture(GL_TEXTURE2); |             data->glActiveTexture(GL_TEXTURE2); | ||||||
|             data->glBindTexture(tdata->texture_type, tdata->texture_v); |             data->glBindTexture(tdata->texture_type, tdata->texture_v); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             data->glActiveTexture(GL_TEXTURE1); |             data->glActiveTexture(GL_TEXTURE1); | ||||||
|             data->glBindTexture(tdata->texture_type, tdata->texture_u); |             data->glBindTexture(tdata->texture_type, tdata->texture_u); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             data->glActiveTexture(GL_TEXTURE0); |             data->glActiveTexture(GL_TEXTURE0); | ||||||
|         } else if (tdata->nv12) { |         } else if (tdata->nv12) { | ||||||
|             data->glActiveTexture(GL_TEXTURE1); |             data->glActiveTexture(GL_TEXTURE1); | ||||||
|             data->glBindTexture(tdata->texture_type, tdata->texture_u); |             data->glBindTexture(tdata->texture_type, tdata->texture_u); | ||||||
|  |  | ||||||
|  |             if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |                 return -1; | ||||||
|  |             } | ||||||
|  |  | ||||||
|             data->glActiveTexture(GL_TEXTURE0); |             data->glActiveTexture(GL_TEXTURE0); | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|         data->glBindTexture(tdata->texture_type, tdata->texture); |         data->glBindTexture(tdata->texture_type, tdata->texture); | ||||||
|  |  | ||||||
|  |         if (SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode) < 0) { | ||||||
|  |             return -1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         data->drawstate.texture = texture; |         data->drawstate.texture = texture; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1552,8 +1586,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL | |||||||
|         renderdata->glBindTexture(data->texture_type, data->texture_v); |         renderdata->glBindTexture(data->texture_type, data->texture_v); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); |         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); | ||||||
|         SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v); |         SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v); | ||||||
|  |  | ||||||
| @@ -1570,8 +1602,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL | |||||||
|         renderdata->glBindTexture(data->texture_type, data->texture_u); |         renderdata->glBindTexture(data->texture_type, data->texture_u); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); |         renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); | ||||||
|         if (GL_CheckError("glTexImage2D()", renderer) < 0) { |         if (GL_CheckError("glTexImage2D()", renderer) < 0) { | ||||||
|             return -1; |             return -1; | ||||||
| @@ -1595,8 +1625,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL | |||||||
|         renderdata->glBindTexture(data->texture_type, data->texture_u); |         renderdata->glBindTexture(data->texture_type, data->texture_u); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |  | ||||||
|         renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); |         renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); | ||||||
|         if (GL_CheckError("glTexImage2D()", renderer) < 0) { |         if (GL_CheckError("glTexImage2D()", renderer) < 0) { | ||||||
|             return -1; |             return -1; | ||||||
| @@ -1623,8 +1651,6 @@ static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL | |||||||
|     renderdata->glBindTexture(data->texture_type, data->texture); |     renderdata->glBindTexture(data->texture_type, data->texture); | ||||||
|     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); | ||||||
|     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); | ||||||
|     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |  | ||||||
|     renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |  | ||||||
|     if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { |     if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { | ||||||
|         renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); |         renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); | ||||||
|         if (GL_CheckError("glTexImage2D()", renderer) < 0) { |         if (GL_CheckError("glTexImage2D()", renderer) < 0) { | ||||||
|   | |||||||
| @@ -928,7 +928,8 @@ static int SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo | |||||||
|                         &(ptr[0].src), &(ptr[1].src), &(ptr[2].src), |                         &(ptr[0].src), &(ptr[1].src), &(ptr[2].src), | ||||||
|                         surface, |                         surface, | ||||||
|                         &(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), |                         &(ptr[0].dst), &(ptr[1].dst), &(ptr[2].dst), | ||||||
|                         ptr[0].color, ptr[1].color, ptr[2].color); |                         ptr[0].color, ptr[1].color, ptr[2].color, | ||||||
|  |                         cmd->data.draw.texture_address_mode); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 GeometryFillData *ptr = (GeometryFillData *)verts; |                 GeometryFillData *ptr = (GeometryFillData *)verts; | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info, | |||||||
|                                   SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, |                                   SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, | ||||||
|                                   int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, |                                   int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, | ||||||
|                                   int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, |                                   int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, | ||||||
|                                   SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform); |                                   SDL_Color c0, SDL_Color c1, SDL_Color c2, SDL_bool is_uniform, SDL_TextureAddressMode texture_address_mode); | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| int SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3]) | int SDL_BlitTriangle(SDL_Surface *src, const SDL_Point srcpoints[3], SDL_Surface *dst, const SDL_Point dstpoints[3]) | ||||||
| @@ -183,7 +183,17 @@ static void bounding_rect(const SDL_Point *a, const SDL_Point *b, const SDL_Poin | |||||||
| /* Use 64 bits precision to prevent overflow when interpolating color / texture with wide triangles */ | /* Use 64 bits precision to prevent overflow when interpolating color / texture with wide triangles */ | ||||||
| #define TRIANGLE_GET_TEXTCOORD                                                          \ | #define TRIANGLE_GET_TEXTCOORD                                                          \ | ||||||
|     int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \ |     int srcx = (int)(((Sint64)w0 * s2s0_x + (Sint64)w1 * s2s1_x + s2_x_area.x) / area); \ | ||||||
|     int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area); |     int srcy = (int)(((Sint64)w0 * s2s0_y + (Sint64)w1 * s2s1_y + s2_x_area.y) / area); \ | ||||||
|  |     if (texture_address_mode == SDL_TEXTURE_ADDRESS_WRAP) {                             \ | ||||||
|  |         srcx %= src_surface->w;                                                         \ | ||||||
|  |         if (srcx < 0) {                                                                 \ | ||||||
|  |             srcx += (src_surface->w - 1);                                               \ | ||||||
|  |         }                                                                               \ | ||||||
|  |         srcy %= src_surface->h;                                                         \ | ||||||
|  |         if (srcy < 0) {                                                                 \ | ||||||
|  |             srcy += (src_surface->h - 1);                                               \ | ||||||
|  |         }                                                                               \ | ||||||
|  |     } | ||||||
|  |  | ||||||
| #define TRIANGLE_GET_MAPPED_COLOR                                                      \ | #define TRIANGLE_GET_MAPPED_COLOR                                                      \ | ||||||
|     Uint8 r = (Uint8)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \ |     Uint8 r = (Uint8)(((Sint64)w0 * c0.r + (Sint64)w1 * c1.r + (Sint64)w2 * c2.r) / area); \ | ||||||
| @@ -231,7 +241,7 @@ int SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poin | |||||||
|     Sint64 w0_row, w1_row, w2_row; |     Sint64 w0_row, w1_row, w2_row; | ||||||
|     int bias_w0, bias_w1, bias_w2; |     int bias_w0, bias_w1, bias_w2; | ||||||
|  |  | ||||||
|     int is_uniform; |     SDL_bool is_uniform; | ||||||
|  |  | ||||||
|     SDL_Surface *tmp = NULL; |     SDL_Surface *tmp = NULL; | ||||||
|  |  | ||||||
| @@ -454,8 +464,10 @@ int SDL_SW_BlitTriangle( | |||||||
|     SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, |     SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, | ||||||
|     SDL_Surface *dst, |     SDL_Surface *dst, | ||||||
|     SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, |     SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||||||
|     SDL_Color c0, SDL_Color c1, SDL_Color c2) |     SDL_Color c0, SDL_Color c1, SDL_Color c2, | ||||||
|  |     SDL_TextureAddressMode texture_address_mode) | ||||||
| { | { | ||||||
|  |     SDL_Surface *src_surface = src; | ||||||
|     int ret = 0; |     int ret = 0; | ||||||
|     int src_locked = 0; |     int src_locked = 0; | ||||||
|     int dst_locked = 0; |     int dst_locked = 0; | ||||||
| @@ -482,9 +494,9 @@ int SDL_SW_BlitTriangle( | |||||||
|     Sint64 w0_row, w1_row, w2_row; |     Sint64 w0_row, w1_row, w2_row; | ||||||
|     int bias_w0, bias_w1, bias_w2; |     int bias_w0, bias_w1, bias_w2; | ||||||
|  |  | ||||||
|     int is_uniform; |     SDL_bool is_uniform; | ||||||
|  |  | ||||||
|     int has_modulation; |     SDL_bool has_modulation; | ||||||
|  |  | ||||||
|     if (!SDL_SurfaceValid(src)) { |     if (!SDL_SurfaceValid(src)) { | ||||||
|         return SDL_InvalidParamError("src"); |         return SDL_InvalidParamError("src"); | ||||||
| @@ -527,7 +539,7 @@ int SDL_SW_BlitTriangle( | |||||||
|     SDL_GetSurfaceBlendMode(src, &blend); |     SDL_GetSurfaceBlendMode(src, &blend); | ||||||
|  |  | ||||||
|     /* TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 */ |     /* TRIANGLE_GET_TEXTCOORD interpolates up to the max values included, so reduce by 1 */ | ||||||
|     { |     if (texture_address_mode == SDL_TEXTURE_ADDRESS_CLAMP) { | ||||||
|         SDL_Rect srcrect; |         SDL_Rect srcrect; | ||||||
|         int maxx, maxy; |         int maxx, maxy; | ||||||
|         bounding_rect(s0, s1, s2, &srcrect); |         bounding_rect(s0, s1, s2, &srcrect); | ||||||
| @@ -564,17 +576,6 @@ int SDL_SW_BlitTriangle( | |||||||
|         has_modulation = SDL_TRUE; |         has_modulation = SDL_TRUE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     { |  | ||||||
|         /* Clip triangle rect with surface rect */ |  | ||||||
|         SDL_Rect rect; |  | ||||||
|         rect.x = 0; |  | ||||||
|         rect.y = 0; |  | ||||||
|         rect.w = dst->w; |  | ||||||
|         rect.h = dst->h; |  | ||||||
|  |  | ||||||
|         SDL_GetRectIntersection(&dstrect, &rect, &dstrect); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     { |     { | ||||||
|         /* Clip triangle with surface clip rect */ |         /* Clip triangle with surface clip rect */ | ||||||
|         SDL_Rect rect; |         SDL_Rect rect; | ||||||
| @@ -695,6 +696,7 @@ int SDL_SW_BlitTriangle( | |||||||
|         tmp_info.colorkey = info->colorkey; |         tmp_info.colorkey = info->colorkey; | ||||||
|  |  | ||||||
|         /* src */ |         /* src */ | ||||||
|  |         tmp_info.src_surface = src_surface; | ||||||
|         tmp_info.src = (Uint8 *)src_ptr; |         tmp_info.src = (Uint8 *)src_ptr; | ||||||
|         tmp_info.src_pitch = src_pitch; |         tmp_info.src_pitch = src_pitch; | ||||||
|  |  | ||||||
| @@ -714,7 +716,7 @@ int SDL_SW_BlitTriangle( | |||||||
|         SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, (int)area, bias_w0, bias_w1, bias_w2, |         SDL_BlitTriangle_Slow(&tmp_info, s2_x_area, dstrect, (int)area, bias_w0, bias_w1, bias_w2, | ||||||
|                               d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x, |                               d2d1_y, d1d2_x, d0d2_y, d2d0_x, d1d0_y, d0d1_x, | ||||||
|                               s2s0_x, s2s1_x, s2s0_y, s2s1_y, (int)w0_row, (int)w1_row, (int)w2_row, |                               s2s0_x, s2s1_x, s2s0_y, s2s1_y, (int)w0_row, (int)w1_row, (int)w2_row, | ||||||
|                               c0, c1, c2, is_uniform); |                               c0, c1, c2, is_uniform, texture_address_mode); | ||||||
|  |  | ||||||
|         goto end; |         goto end; | ||||||
|     } |     } | ||||||
| @@ -786,8 +788,9 @@ static void SDL_BlitTriangle_Slow(SDL_BlitInfo *info, | |||||||
|                                   SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, |                                   SDL_Point s2_x_area, SDL_Rect dstrect, int area, int bias_w0, int bias_w1, int bias_w2, | ||||||
|                                   int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, |                                   int d2d1_y, int d1d2_x, int d0d2_y, int d2d0_x, int d1d0_y, int d0d1_x, | ||||||
|                                   int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, |                                   int s2s0_x, int s2s1_x, int s2s0_y, int s2s1_y, int w0_row, int w1_row, int w2_row, | ||||||
|                                   SDL_Color c0, SDL_Color c1, SDL_Color c2, int is_uniform) |                                   SDL_Color c0, SDL_Color c1, SDL_Color c2, SDL_bool is_uniform, SDL_TextureAddressMode texture_address_mode) | ||||||
| { | { | ||||||
|  |     SDL_Surface *src_surface = info->src_surface; | ||||||
|     const int flags = info->flags; |     const int flags = info->flags; | ||||||
|     Uint32 modulateR = info->r; |     Uint32 modulateR = info->r; | ||||||
|     Uint32 modulateG = info->g; |     Uint32 modulateG = info->g; | ||||||
|   | |||||||
| @@ -24,6 +24,8 @@ | |||||||
|  |  | ||||||
| #include "SDL_internal.h" | #include "SDL_internal.h" | ||||||
|  |  | ||||||
|  | #include "../SDL_sysrender.h"   // For SDL_TextureAddressMode | ||||||
|  |  | ||||||
| extern int SDL_SW_FillTriangle(SDL_Surface *dst, | extern int SDL_SW_FillTriangle(SDL_Surface *dst, | ||||||
|                                SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, |                                SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||||||
|                                SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2); |                                SDL_BlendMode blend, SDL_Color c0, SDL_Color c1, SDL_Color c2); | ||||||
| @@ -33,7 +35,8 @@ extern int SDL_SW_BlitTriangle( | |||||||
|     SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, |     SDL_Point *s0, SDL_Point *s1, SDL_Point *s2, | ||||||
|     SDL_Surface *dst, |     SDL_Surface *dst, | ||||||
|     SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, |     SDL_Point *d0, SDL_Point *d1, SDL_Point *d2, | ||||||
|     SDL_Color c0, SDL_Color c1, SDL_Color c2); |     SDL_Color c0, SDL_Color c1, SDL_Color c2, | ||||||
|  |     SDL_TextureAddressMode texture_address_mode); | ||||||
|  |  | ||||||
| extern void trianglepoint_2_fixedpoint(SDL_Point *a); | extern void trianglepoint_2_fixedpoint(SDL_Point *a); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -158,9 +158,12 @@ typedef enum { | |||||||
| } SDL_vulkan_renderpass_type; | } SDL_vulkan_renderpass_type; | ||||||
|  |  | ||||||
| /* Sampler types */ | /* Sampler types */ | ||||||
| typedef enum { | typedef enum | ||||||
|     SDL_VULKAN_SAMPLER_NEAREST = 0, | { | ||||||
|     SDL_VULKAN_SAMPLER_LINEAR = 1, |     SDL_VULKAN_SAMPLER_NEAREST_CLAMP, | ||||||
|  |     SDL_VULKAN_SAMPLER_NEAREST_WRAP, | ||||||
|  |     SDL_VULKAN_SAMPLER_LINEAR_CLAMP, | ||||||
|  |     SDL_VULKAN_SAMPLER_LINEAR_WRAP, | ||||||
|     SDL_VULKAN_NUM_SAMPLERS |     SDL_VULKAN_NUM_SAMPLERS | ||||||
| } SDL_vulkan_sampler_type; | } SDL_vulkan_sampler_type; | ||||||
|  |  | ||||||
| @@ -181,6 +184,15 @@ static const float INPUTTYPE_SRGB = 1; | |||||||
| static const float INPUTTYPE_SCRGB = 2; | static const float INPUTTYPE_SCRGB = 2; | ||||||
| static const float INPUTTYPE_HDR10 = 3; | static const float INPUTTYPE_HDR10 = 3; | ||||||
|  |  | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |     SAMPLER_POINT_CLAMP, | ||||||
|  |     SAMPLER_POINT_WRAP, | ||||||
|  |     SAMPLER_LINEAR_CLAMP, | ||||||
|  |     SAMPLER_LINEAR_WRAP, | ||||||
|  |     NUM_SAMPLERS | ||||||
|  | } Sampler; | ||||||
|  |  | ||||||
| /* Pixel shader constants, common values */ | /* Pixel shader constants, common values */ | ||||||
| typedef struct | typedef struct | ||||||
| { | { | ||||||
| @@ -1904,34 +1916,37 @@ static VkResult VULKAN_CreateDeviceResources(SDL_Renderer *renderer, SDL_Propert | |||||||
|  |  | ||||||
|     /* Create samplers */ |     /* Create samplers */ | ||||||
|     { |     { | ||||||
|  |         static struct | ||||||
|  |         { | ||||||
|  |             VkFilter filter; | ||||||
|  |             VkSamplerAddressMode address; | ||||||
|  |         } samplerParams[] = { | ||||||
|  |             { VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE }, | ||||||
|  |             { VK_FILTER_NEAREST, VK_SAMPLER_ADDRESS_MODE_REPEAT }, | ||||||
|  |             { VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE }, | ||||||
|  |             { VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT }, | ||||||
|  |         }; | ||||||
|  |         SDL_COMPILE_TIME_ASSERT(samplerParams_SIZE, SDL_arraysize(samplerParams) == SDL_VULKAN_NUM_SAMPLERS); | ||||||
|         VkSamplerCreateInfo samplerCreateInfo = { 0 }; |         VkSamplerCreateInfo samplerCreateInfo = { 0 }; | ||||||
|         samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; |         samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; | ||||||
|         samplerCreateInfo.magFilter = VK_FILTER_NEAREST; |  | ||||||
|         samplerCreateInfo.minFilter = VK_FILTER_NEAREST; |  | ||||||
|         samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; |         samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; | ||||||
|         samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |  | ||||||
|         samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |  | ||||||
|         samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |         samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; | ||||||
|         samplerCreateInfo.mipLodBias = 0.0f; |         samplerCreateInfo.mipLodBias = 0.0f; | ||||||
|         samplerCreateInfo.anisotropyEnable = VK_FALSE; |         samplerCreateInfo.anisotropyEnable = VK_FALSE; | ||||||
|         samplerCreateInfo.maxAnisotropy = 1.0f; |         samplerCreateInfo.maxAnisotropy = 1.0f; | ||||||
|         samplerCreateInfo.minLod = 0.0f; |         samplerCreateInfo.minLod = 0.0f; | ||||||
|         samplerCreateInfo.maxLod = 1000.0f; |         samplerCreateInfo.maxLod = 1000.0f; | ||||||
|         result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST]); |         for (int i = 0; i < SDL_arraysize(samplerParams); ++i) { | ||||||
|         if (result != VK_SUCCESS) { |             samplerCreateInfo.magFilter = samplerParams[i].filter; | ||||||
|             VULKAN_DestroyAll(renderer); |             samplerCreateInfo.minFilter = samplerParams[i].filter; | ||||||
|             SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result)); |             samplerCreateInfo.addressModeU = samplerParams[i].address; | ||||||
|             return result; |             samplerCreateInfo.addressModeV = samplerParams[i].address; | ||||||
|         } |             result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[i]); | ||||||
|  |             if (result != VK_SUCCESS) { | ||||||
|         samplerCreateInfo.magFilter = VK_FILTER_LINEAR; |                 VULKAN_DestroyAll(renderer); | ||||||
|         samplerCreateInfo.minFilter = VK_FILTER_LINEAR; |                 SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result)); | ||||||
|         samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; |                 return result; | ||||||
|         result = vkCreateSampler(rendererData->device, &samplerCreateInfo, NULL, &rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR]); |             } | ||||||
|         if (result != VK_SUCCESS) { |  | ||||||
|             VULKAN_DestroyAll(renderer); |  | ||||||
|             SDL_LogError(SDL_LOG_CATEGORY_RENDER, "vkCreateSampler(): %s\n", SDL_Vulkan_GetResultString(result)); |  | ||||||
|             return result; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2602,8 +2617,8 @@ static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD | |||||||
|         samplerCreateInfo.magFilter = VK_FILTER_NEAREST; |         samplerCreateInfo.magFilter = VK_FILTER_NEAREST; | ||||||
|         samplerCreateInfo.minFilter = VK_FILTER_NEAREST; |         samplerCreateInfo.minFilter = VK_FILTER_NEAREST; | ||||||
|         samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; |         samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; | ||||||
|         samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |         samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; | ||||||
|         samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |         samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; | ||||||
|         samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; |         samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; | ||||||
|         samplerCreateInfo.mipLodBias = 0.0f; |         samplerCreateInfo.mipLodBias = 0.0f; | ||||||
|         samplerCreateInfo.anisotropyEnable = VK_FALSE; |         samplerCreateInfo.anisotropyEnable = VK_FALSE; | ||||||
| @@ -3627,10 +3642,28 @@ static SDL_bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderComm | |||||||
|  |  | ||||||
|     switch (textureData->scaleMode) { |     switch (textureData->scaleMode) { | ||||||
|     case VK_FILTER_NEAREST: |     case VK_FILTER_NEAREST: | ||||||
|         textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST]; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_NEAREST_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     case VK_FILTER_LINEAR: |     case VK_FILTER_LINEAR: | ||||||
|         textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR]; |         switch (cmd->data.draw.texture_address_mode) { | ||||||
|  |         case SDL_TEXTURE_ADDRESS_CLAMP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR_CLAMP]; | ||||||
|  |             break; | ||||||
|  |         case SDL_TEXTURE_ADDRESS_WRAP: | ||||||
|  |             textureSampler = rendererData->samplers[SDL_VULKAN_SAMPLER_LINEAR_WRAP]; | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             return SDL_SetError("Unknown texture address mode: %d\n", cmd->data.draw.texture_address_mode); | ||||||
|  |         } | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode); |         return SDL_SetError("Unknown scale mode: %d", textureData->scaleMode); | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -23,9 +23,10 @@ typedef struct SDLTest_SurfaceImage_s { | |||||||
| } SDLTest_SurfaceImage_t; | } SDLTest_SurfaceImage_t; | ||||||
|  |  | ||||||
| /* Test images */ | /* Test images */ | ||||||
| SDL_Surface *SDLTest_ImageBlit(void); | extern SDL_Surface *SDLTest_ImageBlit(void); | ||||||
| SDL_Surface *SDLTest_ImageBlitColor(void); | extern SDL_Surface *SDLTest_ImageBlitColor(void); | ||||||
| SDL_Surface *SDLTest_ImageFace(void); | extern SDL_Surface *SDLTest_ImageFace(void); | ||||||
| SDL_Surface *SDLTest_ImagePrimitives(void); | extern SDL_Surface *SDLTest_ImagePrimitives(void); | ||||||
| SDL_Surface *SDLTest_ImageBlendingBackground(void); | extern SDL_Surface *SDLTest_ImageBlendingBackground(void); | ||||||
| SDL_Surface *SDLTest_ImageBlendingSprite(void); | extern SDL_Surface *SDLTest_ImageBlendingSprite(void); | ||||||
|  | extern SDL_Surface *SDLTest_ImageWrappingSprite(void); | ||||||
|   | |||||||
| @@ -1076,6 +1076,109 @@ clearScreen(void) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Tests geometry UV wrapping | ||||||
|  |  */ | ||||||
|  | static int render_testUVWrapping(void *arg) | ||||||
|  | { | ||||||
|  |     SDL_Vertex vertices[6]; | ||||||
|  |     SDL_Vertex *verts = vertices; | ||||||
|  |     SDL_FColor color = { 1.0f, 1.0f, 1.0f, 1.0f }; | ||||||
|  |     float tw, th; | ||||||
|  |     SDL_FRect rect; | ||||||
|  |     float min_U = -0.5f; | ||||||
|  |     float max_U = 1.5f; | ||||||
|  |     float min_V = -0.5f; | ||||||
|  |     float max_V = 1.5f; | ||||||
|  |     SDL_Texture *tface; | ||||||
|  |     SDL_Surface *referenceSurface = NULL; | ||||||
|  |  | ||||||
|  |     /* Clear surface. */ | ||||||
|  |     clearScreen(); | ||||||
|  |  | ||||||
|  |     /* Create face surface. */ | ||||||
|  |     tface = loadTestFace(); | ||||||
|  |     SDLTest_AssertCheck(tface != NULL, "Verify loadTestFace() result"); | ||||||
|  |     if (tface == NULL) { | ||||||
|  |         return TEST_ABORTED; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     CHECK_FUNC(SDL_GetTextureSize, (tface, &tw, &th)) | ||||||
|  |     rect.w = tw * 2; | ||||||
|  |     rect.h = th * 2; | ||||||
|  |     rect.x = (TESTRENDER_SCREEN_W - rect.w) / 2; | ||||||
|  |     rect.y = (TESTRENDER_SCREEN_H - rect.h) / 2; | ||||||
|  |  | ||||||
|  |     /* | ||||||
|  |      *   0--1 | ||||||
|  |      *   | /| | ||||||
|  |      *   |/ | | ||||||
|  |      *   3--2 | ||||||
|  |      * | ||||||
|  |      *  Draw sprite2 as triangles that can be recombined as rect by software renderer | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     /* 0 */ | ||||||
|  |     verts->position.x = rect.x; | ||||||
|  |     verts->position.y = rect.y; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = min_U; | ||||||
|  |     verts->tex_coord.y = min_V; | ||||||
|  |     verts++; | ||||||
|  |     /* 1 */ | ||||||
|  |     verts->position.x = rect.x + rect.w; | ||||||
|  |     verts->position.y = rect.y; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = max_U; | ||||||
|  |     verts->tex_coord.y = min_V; | ||||||
|  |     verts++; | ||||||
|  |     /* 2 */ | ||||||
|  |     verts->position.x = rect.x + rect.w; | ||||||
|  |     verts->position.y = rect.y + rect.h; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = max_U; | ||||||
|  |     verts->tex_coord.y = max_V; | ||||||
|  |     verts++; | ||||||
|  |     /* 0 */ | ||||||
|  |     verts->position.x = rect.x; | ||||||
|  |     verts->position.y = rect.y; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = min_U; | ||||||
|  |     verts->tex_coord.y = min_V; | ||||||
|  |     verts++; | ||||||
|  |     /* 2 */ | ||||||
|  |     verts->position.x = rect.x + rect.w; | ||||||
|  |     verts->position.y = rect.y + rect.h; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = max_U; | ||||||
|  |     verts->tex_coord.y = max_V; | ||||||
|  |     verts++; | ||||||
|  |     /* 3 */ | ||||||
|  |     verts->position.x = rect.x; | ||||||
|  |     verts->position.y = rect.y + rect.h; | ||||||
|  |     verts->color = color; | ||||||
|  |     verts->tex_coord.x = min_U; | ||||||
|  |     verts->tex_coord.y = max_V; | ||||||
|  |     verts++; | ||||||
|  |  | ||||||
|  |     /* Blit sprites as triangles onto the screen */ | ||||||
|  |     SDL_RenderGeometry(renderer, tface, vertices, 6, NULL, 0); | ||||||
|  |  | ||||||
|  |     /* See if it's the same */ | ||||||
|  |     referenceSurface = SDLTest_ImageWrappingSprite(); | ||||||
|  |     compare(referenceSurface, ALLOWABLE_ERROR_OPAQUE); | ||||||
|  |  | ||||||
|  |     /* Make current */ | ||||||
|  |     SDL_RenderPresent(renderer); | ||||||
|  |  | ||||||
|  |     /* Clean up. */ | ||||||
|  |     SDL_DestroyTexture(tface); | ||||||
|  |     SDL_DestroySurface(referenceSurface); | ||||||
|  |     referenceSurface = NULL; | ||||||
|  |  | ||||||
|  |     return TEST_COMPLETED; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* ================= Test References ================== */ | /* ================= Test References ================== */ | ||||||
|  |  | ||||||
| /* Render test cases */ | /* Render test cases */ | ||||||
| @@ -1115,11 +1218,15 @@ static const SDLTest_TestCaseReference renderTest9 = { | |||||||
|     (SDLTest_TestCaseFp)render_testLogicalSize, "render_testLogicalSize", "Tests logical size", TEST_ENABLED |     (SDLTest_TestCaseFp)render_testLogicalSize, "render_testLogicalSize", "Tests logical size", TEST_ENABLED | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static const SDLTest_TestCaseReference renderTestUVWrapping = { | ||||||
|  |     (SDLTest_TestCaseFp)render_testUVWrapping, "render_testUVWrapping", "Tests geometry UV wrapping", TEST_ENABLED | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* Sequence of Render test cases */ | /* Sequence of Render test cases */ | ||||||
| static const SDLTest_TestCaseReference *renderTests[] = { | static const SDLTest_TestCaseReference *renderTests[] = { | ||||||
|     &renderTest1, &renderTest2, &renderTest3, &renderTest4, |     &renderTest1, &renderTest2, &renderTest3, &renderTest4, | ||||||
|     &renderTest5, &renderTest6, &renderTest7, &renderTest8, |     &renderTest5, &renderTest6, &renderTest7, &renderTest8, | ||||||
|     &renderTest9, NULL |     &renderTest9, &renderTestUVWrapping, NULL | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* Render test suite (global) */ | /* Render test suite (global) */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sam Lantinga
					Sam Lantinga