mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	Backends: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464)
Backends: Normalize clipping rect handling across backends. + Squashed amends.
This commit is contained in:
		| @@ -171,9 +171,15 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data) | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Draw | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); | ||||
|                 ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply scissor/clipping rectangle, Draw | ||||
|                 ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID(); | ||||
|                 al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y); | ||||
|                 al_set_clipping_rectangle(clip_min.x, clip_min.y, clip_max.x, clip_max.y); | ||||
|                 al_draw_prim(&vertices[0], bd->VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST); | ||||
|             } | ||||
|             idx_offset += pcmd->ElemCount; | ||||
|   | ||||
| @@ -253,8 +253,14 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); | ||||
|                 ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply scissor/clipping rectangle | ||||
|                 const D3D10_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y)}; | ||||
|                 const D3D10_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; | ||||
|                 ctx->RSSetScissorRects(1, &r); | ||||
|  | ||||
|                 // Bind texture, Draw | ||||
|   | ||||
| @@ -263,8 +263,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); | ||||
|                 ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply scissor/clipping rectangle | ||||
|                 const D3D11_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; | ||||
|                 const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; | ||||
|                 ctx->RSSetScissorRects(1, &r); | ||||
|  | ||||
|                 // Bind texture, Draw | ||||
|   | ||||
| @@ -259,10 +259,14 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Apply Scissor, Bind texture, Draw | ||||
|                 const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; | ||||
|                 if (r.right > r.left && r.bottom > r.top) | ||||
|                 { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); | ||||
|                 ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply Scissor/clipping rectangle, Bind texture, Draw | ||||
|                 const D3D12_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; | ||||
|                 D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {}; | ||||
|                 texture_handle.ptr = (UINT64)pcmd->GetTexID(); | ||||
|                 ctx->SetGraphicsRootDescriptorTable(1, texture_handle); | ||||
| @@ -270,7 +274,6 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL | ||||
|                 ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); | ||||
|             } | ||||
|         } | ||||
|         } | ||||
|         global_idx_offset += cmd_list->IdxBuffer.Size; | ||||
|         global_vtx_offset += cmd_list->VtxBuffer.Size; | ||||
|     } | ||||
|   | ||||
| @@ -248,7 +248,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) }; | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); | ||||
|                 ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply Scissor/clipping rectangle, Bind texture, Draw | ||||
|                 const RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; | ||||
|                 const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID(); | ||||
|                 bd->pd3dDevice->SetTexture(0, texture); | ||||
|                 bd->pd3dDevice->SetScissorRect(&r); | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
|  | ||||
| // CHANGELOG | ||||
| // (minor and older changes stripped away, please see git history for details) | ||||
| //  2021-08-24: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted. (#4464) | ||||
| //  2021-05-19: Metal: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) | ||||
| //  2021-02-18: Metal: Change blending equation to preserve alpha in output buffer. | ||||
| //  2021-01-25: Metal: Fixed texture storage mode when building on Mac Catalyst. | ||||
| @@ -504,25 +505,27 @@ void ImGui_ImplMetal_DestroyDeviceObjects() | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec4 clip_rect; | ||||
|                 clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; | ||||
|                 clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|  | ||||
|                 // Clamp to viewport as setScissorRect() won't accept values that are off bounds | ||||
|                 if (clip_min.x < 0.0f) { clip_min.x = 0.0f; } | ||||
|                 if (clip_min.y < 0.0f) { clip_min.y = 0.0f; } | ||||
|                 if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; } | ||||
|                 if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; } | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) | ||||
|                 { | ||||
|                 // Apply scissor/clipping rectangle | ||||
|                 MTLScissorRect scissorRect = | ||||
|                 { | ||||
|                         .x = NSUInteger(clip_rect.x), | ||||
|                         .y = NSUInteger(clip_rect.y), | ||||
|                         .width = NSUInteger(clip_rect.z - clip_rect.x), | ||||
|                         .height = NSUInteger(clip_rect.w - clip_rect.y) | ||||
|                     .x = NSUInteger(clip_min.x), | ||||
|                     .y = NSUInteger(clip_min.y), | ||||
|                     .width = NSUInteger(clip_max.x - clip_min.x), | ||||
|                     .height = NSUInteger(clip_max.y - clip_min.y) | ||||
|                 }; | ||||
|                 [commandEncoder setScissorRect:scissorRect]; | ||||
|  | ||||
|  | ||||
|                 // Bind texture, Draw | ||||
|                 if (ImTextureID tex_id = pcmd->GetTexID()) | ||||
|                     [commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(tex_id) atIndex:0]; | ||||
| @@ -535,7 +538,6 @@ void ImGui_ImplMetal_DestroyDeviceObjects() | ||||
|                                     indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)]; | ||||
|             } | ||||
|         } | ||||
|         } | ||||
|  | ||||
|         vertexBufferOffset += (size_t)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); | ||||
|         indexBufferOffset += (size_t)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx); | ||||
|   | ||||
| @@ -200,22 +200,18 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec4 clip_rect; | ||||
|                 clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; | ||||
|                 clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) | ||||
|                 { | ||||
|                     // Apply scissor/clipping rectangle | ||||
|                     glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); | ||||
|                 // Apply scissor/clipping rectangle (Y is inverted in OpenGL) | ||||
|                 glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); | ||||
|  | ||||
|                 // Bind texture, Draw | ||||
|                 glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); | ||||
|                 glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer); | ||||
|             } | ||||
|             } | ||||
|             idx_buffer += pcmd->ElemCount; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -442,16 +442,13 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec4 clip_rect; | ||||
|                 clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; | ||||
|                 clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) | ||||
|                 { | ||||
|                     // Apply scissor/clipping rectangle | ||||
|                     glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); | ||||
|                 // Apply scissor/clipping rectangle (Y is inverted in OpenGL) | ||||
|                 glScissor((int)clip_min.x, (int)(fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)); | ||||
|  | ||||
|                 // Bind texture, Draw | ||||
|                 glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()); | ||||
| @@ -464,7 +461,6 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     } | ||||
|  | ||||
|     // Destroy the temporary VAO | ||||
| #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY | ||||
|   | ||||
| @@ -511,33 +511,29 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm | ||||
|             else | ||||
|             { | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec4 clip_rect; | ||||
|                 clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y; | ||||
|                 clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x; | ||||
|                 clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|  | ||||
|                 if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f) | ||||
|                 { | ||||
|                     // Negative offsets are illegal for vkCmdSetScissor | ||||
|                     if (clip_rect.x < 0.0f) | ||||
|                         clip_rect.x = 0.0f; | ||||
|                     if (clip_rect.y < 0.0f) | ||||
|                         clip_rect.y = 0.0f; | ||||
|                 // Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds | ||||
|                 if (clip_min.x < 0.0f) { clip_min.x = 0.0f; } | ||||
|                 if (clip_min.y < 0.0f) { clip_min.y = 0.0f; } | ||||
|                 if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; } | ||||
|                 if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; } | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply scissor/clipping rectangle | ||||
|                 VkRect2D scissor; | ||||
|                     scissor.offset.x = (int32_t)(clip_rect.x); | ||||
|                     scissor.offset.y = (int32_t)(clip_rect.y); | ||||
|                     scissor.extent.width = (uint32_t)(clip_rect.z - clip_rect.x); | ||||
|                     scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y); | ||||
|                 scissor.offset.x = (int32_t)(clip_min.x); | ||||
|                 scissor.offset.y = (int32_t)(clip_min.y); | ||||
|                 scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x); | ||||
|                 scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y); | ||||
|                 vkCmdSetScissor(command_buffer, 0, 1, &scissor); | ||||
|  | ||||
|                 // Draw | ||||
|                 vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); | ||||
|             } | ||||
|         } | ||||
|         } | ||||
|         global_idx_offset += cmd_list->IdxBuffer.Size; | ||||
|         global_vtx_offset += cmd_list->VtxBuffer.Size; | ||||
|     } | ||||
|   | ||||
| @@ -443,13 +443,14 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder | ||||
|                     wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, NULL); | ||||
|                 } | ||||
|  | ||||
|                 // Apply Scissor, Bind texture, Draw | ||||
|                 uint32_t clip_rect[4]; | ||||
|                 clip_rect[0] = (uint32_t)(clip_scale.x * (pcmd->ClipRect.x - clip_off.x)); | ||||
|                 clip_rect[1] = (uint32_t)(clip_scale.y * (pcmd->ClipRect.y - clip_off.y)); | ||||
|                 clip_rect[2] = (uint32_t)(clip_scale.x * (pcmd->ClipRect.z - clip_off.x)); | ||||
|                 clip_rect[3] = (uint32_t)(clip_scale.y * (pcmd->ClipRect.w - clip_off.y)); | ||||
|                 wgpuRenderPassEncoderSetScissorRect(pass_encoder, clip_rect[0], clip_rect[1], clip_rect[2] - clip_rect[0], clip_rect[3] - clip_rect[1]); | ||||
|                 // Project scissor/clipping rectangles into framebuffer space | ||||
|                 ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y); | ||||
|                 ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y); | ||||
|                 if (clip_max.x < clip_min.x || clip_max.y < clip_min.y) | ||||
|                     continue; | ||||
|  | ||||
|                 // Apply scissor/clipping rectangle, Draw | ||||
|                 wgpuRenderPassEncoderSetScissorRect(pass_encoder, (uint32_t)clip_min.x, (uint32_t)clip_min.y, (uint32_t)(clip_max.x - clip_min.x), (uint32_t)(clip_max.y - clip_min.y)); | ||||
|                 wgpuRenderPassEncoderDrawIndexed(pass_encoder, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0); | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -49,6 +49,9 @@ Other Changes: | ||||
| - Fonts: Fixed ImFontAtlas::ClearInputData() marking atlas as not built. (#4455, #3487) | ||||
| - Backends: OpenGL3: Fixed our new GL loader conflicting with user using GL3W. (#4445) | ||||
| - Backends: WebGPU: Fixed for latest specs. (#4472) [@Kangz] | ||||
| - Backends: Metal: Fixed a crash when clipping rect larger than framebuffer is submitted via | ||||
|   a direct unclipped PushClipRect() call. (#4464) | ||||
| - Backends: All renderers: Normalize clipping rect handling across backends. (#4464) | ||||
|  | ||||
|  | ||||
| ----------------------------------------------------------------------- | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Rokas Kupstys
					Rokas Kupstys