| 2141 | } |
| 2142 | |
| 2143 | Error RenderingDevice::texture_get_data_async(RID p_texture, uint32_t p_layer, const Callable &p_callback) { |
| 2144 | ERR_RENDER_THREAD_GUARD_V(ERR_UNAVAILABLE); |
| 2145 | |
| 2146 | Texture *tex = texture_owner.get_or_null(p_texture); |
| 2147 | ERR_FAIL_NULL_V(tex, ERR_INVALID_PARAMETER); |
| 2148 | |
| 2149 | ERR_FAIL_COND_V_MSG(tex->bound, ERR_INVALID_PARAMETER, "Texture can't be retrieved while a draw list that uses it as part of a framebuffer is being created. Ensure the draw list is finalized (and that the color/depth texture using it is not set to `RenderingDevice.FINAL_ACTION_CONTINUE`) to retrieve this texture."); |
| 2150 | ERR_FAIL_COND_V_MSG(!(tex->usage_flags & TEXTURE_USAGE_CAN_COPY_FROM_BIT), ERR_INVALID_PARAMETER, "Texture requires the `RenderingDevice.TEXTURE_USAGE_CAN_COPY_FROM_BIT` to be set to be retrieved."); |
| 2151 | ERR_FAIL_COND_V(p_layer >= tex->layers, ERR_INVALID_PARAMETER); |
| 2152 | |
| 2153 | // Clear the texture if the driver requires it during its first use. |
| 2154 | _texture_check_pending_clear(p_texture, tex); |
| 2155 | |
| 2156 | _check_transfer_worker_texture(tex); |
| 2157 | |
| 2158 | thread_local LocalVector<RDD::TextureCopyableLayout> mip_layouts; |
| 2159 | mip_layouts.resize(tex->mipmaps); |
| 2160 | for (uint32_t i = 0; i < tex->mipmaps; i++) { |
| 2161 | RDD::TextureSubresource subres; |
| 2162 | subres.aspect = RDD::TEXTURE_ASPECT_COLOR; |
| 2163 | subres.layer = p_layer; |
| 2164 | subres.mipmap = i; |
| 2165 | driver->texture_get_copyable_layout(tex->driver_id, subres, &mip_layouts[i]); |
| 2166 | |
| 2167 | // Assuming layers are tightly packed. If this is not true on some driver, we must modify the copy algorithm. |
| 2168 | DEV_ASSERT(mip_layouts[i].layer_pitch == mip_layouts[i].size / tex->layers); |
| 2169 | } |
| 2170 | |
| 2171 | ERR_FAIL_COND_V(mip_layouts.is_empty(), ERR_INVALID_PARAMETER); |
| 2172 | |
| 2173 | if (_texture_make_mutable(tex, p_texture)) { |
| 2174 | // The texture must be mutable to be used as a copy source due to layout transitions. |
| 2175 | draw_graph.add_synchronization(); |
| 2176 | } |
| 2177 | |
| 2178 | TextureGetDataRequest get_data_request; |
| 2179 | get_data_request.callback = p_callback; |
| 2180 | get_data_request.frame_local_index = frames[frame].download_buffer_texture_copy_regions.size(); |
| 2181 | get_data_request.width = tex->width; |
| 2182 | get_data_request.height = tex->height; |
| 2183 | get_data_request.depth = tex->depth; |
| 2184 | get_data_request.format = tex->format; |
| 2185 | get_data_request.mipmaps = tex->mipmaps; |
| 2186 | |
| 2187 | uint32_t block_w, block_h; |
| 2188 | get_compressed_image_format_block_dimensions(tex->format, block_w, block_h); |
| 2189 | |
| 2190 | uint32_t pixel_size = get_image_format_pixel_size(tex->format); |
| 2191 | uint32_t pixel_rshift = get_compressed_image_format_pixel_rshift(tex->format); |
| 2192 | |
| 2193 | uint32_t w, h, d; |
| 2194 | uint32_t required_align = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_TRANSFER_ALIGNMENT); |
| 2195 | uint32_t pitch_step = driver->api_trait_get(RDD::API_TRAIT_TEXTURE_DATA_ROW_PITCH_STEP); |
| 2196 | uint32_t region_size = texture_download_region_size_px; |
| 2197 | uint32_t logic_w = tex->width; |
| 2198 | uint32_t logic_h = tex->height; |
| 2199 | uint32_t mipmap_offset = 0; |
| 2200 | uint32_t block_write_offset; |
nothing calls this directly
no test coverage detected