2 * Copyright 2002-2005 Jason Edmeades
3 * Copyright 2002-2005 Raphael Junqueira
4 * Copyright 2005 Oliver Stieber
5 * Copyright 2007-2009, 2013 Stefan Dösinger for CodeWeavers
6 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_perf
);
29 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
31 #define WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD 50
33 static const uint32_t wined3d_texture_sysmem_locations
= WINED3D_LOCATION_SYSMEM
| WINED3D_LOCATION_BUFFER
;
34 static const struct wined3d_texture_ops texture_gl_ops
;
36 struct wined3d_texture_idx
38 struct wined3d_texture
*texture
;
39 unsigned int sub_resource_idx
;
50 static BOOL
wined3d_texture_use_pbo(const struct wined3d_texture
*texture
, const struct wined3d_gl_info
*gl_info
)
52 if (!gl_info
->supported
[ARB_PIXEL_BUFFER_OBJECT
]
53 || texture
->resource
.format
->conv_byte_count
54 || (texture
->flags
& (WINED3D_TEXTURE_PIN_SYSMEM
| WINED3D_TEXTURE_COND_NP2_EMULATED
)))
57 /* Use a PBO for dynamic textures and read-only staging textures. */
58 return (!(texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_CPU
)
59 && texture
->resource
.usage
& WINED3DUSAGE_DYNAMIC
)
60 || texture
->resource
.access
== (WINED3D_RESOURCE_ACCESS_CPU
| WINED3D_RESOURCE_ACCESS_MAP_R
);
63 static BOOL
wined3d_texture_use_immutable_storage(const struct wined3d_texture
*texture
,
64 const struct wined3d_gl_info
*gl_info
)
66 /* We don't expect to create texture views for textures with height-scaled formats.
67 * Besides, ARB_texture_storage doesn't allow specifying exact sizes for all levels. */
68 return gl_info
->supported
[ARB_TEXTURE_STORAGE
]
69 && !(texture
->resource
.format_flags
& WINED3DFMT_FLAG_HEIGHT_SCALE
);
72 /* Front buffer coordinates are always full screen coordinates, but our GL
73 * drawable is limited to the window's client area. The sysmem and texture
74 * copies do have the full screen size. Note that GL has a bottom-left
75 * origin, while D3D has a top-left origin. */
76 void wined3d_texture_translate_drawable_coords(const struct wined3d_texture
*texture
, HWND window
, RECT
*rect
)
78 unsigned int drawable_height
;
79 POINT offset
= {0, 0};
82 if (!texture
->swapchain
)
85 if (texture
== texture
->swapchain
->front_buffer
)
87 ScreenToClient(window
, &offset
);
88 OffsetRect(rect
, offset
.x
, offset
.y
);
91 GetClientRect(window
, &windowsize
);
92 drawable_height
= windowsize
.bottom
- windowsize
.top
;
94 rect
->top
= drawable_height
- rect
->top
;
95 rect
->bottom
= drawable_height
- rect
->bottom
;
98 GLenum
wined3d_texture_get_gl_buffer(const struct wined3d_texture
*texture
)
100 const struct wined3d_swapchain
*swapchain
= texture
->swapchain
;
102 TRACE("texture %p.\n", texture
);
106 ERR("Texture %p is not part of a swapchain.\n", texture
);
110 if (texture
== swapchain
->front_buffer
)
112 TRACE("Returning GL_FRONT.\n");
116 if (texture
== swapchain
->back_buffers
[0])
118 TRACE("Returning GL_BACK.\n");
122 FIXME("Higher back buffer, returning GL_BACK.\n");
126 static DWORD
wined3d_resource_access_from_location(DWORD location
)
130 case WINED3D_LOCATION_DISCARDED
:
133 case WINED3D_LOCATION_SYSMEM
:
134 return WINED3D_RESOURCE_ACCESS_CPU
;
136 case WINED3D_LOCATION_BUFFER
:
137 case WINED3D_LOCATION_DRAWABLE
:
138 case WINED3D_LOCATION_TEXTURE_RGB
:
139 case WINED3D_LOCATION_TEXTURE_SRGB
:
140 case WINED3D_LOCATION_RB_MULTISAMPLE
:
141 case WINED3D_LOCATION_RB_RESOLVED
:
142 return WINED3D_RESOURCE_ACCESS_GPU
;
145 FIXME("Unhandled location %#x.\n", location
);
150 static inline void cube_coords_float(const RECT
*r
, UINT w
, UINT h
, struct wined3d_rect_f
*f
)
152 f
->l
= ((r
->left
* 2.0f
) / w
) - 1.0f
;
153 f
->t
= ((r
->top
* 2.0f
) / h
) - 1.0f
;
154 f
->r
= ((r
->right
* 2.0f
) / w
) - 1.0f
;
155 f
->b
= ((r
->bottom
* 2.0f
) / h
) - 1.0f
;
158 void texture2d_get_blt_info(const struct wined3d_texture_gl
*texture_gl
,
159 unsigned int sub_resource_idx
, const RECT
*rect
, struct wined3d_blt_info
*info
)
161 struct wined3d_vec3
*coords
= info
->texcoords
;
162 struct wined3d_rect_f f
;
167 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
168 w
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
169 h
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
170 target
= wined3d_texture_gl_get_sub_resource_target(texture_gl
, sub_resource_idx
);
175 FIXME("Unsupported texture target %#x.\n", target
);
176 /* Fall back to GL_TEXTURE_2D */
178 info
->bind_target
= GL_TEXTURE_2D
;
179 coords
[0].x
= (float)rect
->left
/ w
;
180 coords
[0].y
= (float)rect
->top
/ h
;
183 coords
[1].x
= (float)rect
->right
/ w
;
184 coords
[1].y
= (float)rect
->top
/ h
;
187 coords
[2].x
= (float)rect
->left
/ w
;
188 coords
[2].y
= (float)rect
->bottom
/ h
;
191 coords
[3].x
= (float)rect
->right
/ w
;
192 coords
[3].y
= (float)rect
->bottom
/ h
;
196 case GL_TEXTURE_RECTANGLE_ARB
:
197 info
->bind_target
= GL_TEXTURE_RECTANGLE_ARB
;
198 coords
[0].x
= rect
->left
; coords
[0].y
= rect
->top
; coords
[0].z
= 0.0f
;
199 coords
[1].x
= rect
->right
; coords
[1].y
= rect
->top
; coords
[1].z
= 0.0f
;
200 coords
[2].x
= rect
->left
; coords
[2].y
= rect
->bottom
; coords
[2].z
= 0.0f
;
201 coords
[3].x
= rect
->right
; coords
[3].y
= rect
->bottom
; coords
[3].z
= 0.0f
;
204 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
205 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
206 cube_coords_float(rect
, w
, h
, &f
);
208 coords
[0].x
= 1.0f
; coords
[0].y
= -f
.t
; coords
[0].z
= -f
.l
;
209 coords
[1].x
= 1.0f
; coords
[1].y
= -f
.t
; coords
[1].z
= -f
.r
;
210 coords
[2].x
= 1.0f
; coords
[2].y
= -f
.b
; coords
[2].z
= -f
.l
;
211 coords
[3].x
= 1.0f
; coords
[3].y
= -f
.b
; coords
[3].z
= -f
.r
;
214 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
215 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
216 cube_coords_float(rect
, w
, h
, &f
);
218 coords
[0].x
= -1.0f
; coords
[0].y
= -f
.t
; coords
[0].z
= f
.l
;
219 coords
[1].x
= -1.0f
; coords
[1].y
= -f
.t
; coords
[1].z
= f
.r
;
220 coords
[2].x
= -1.0f
; coords
[2].y
= -f
.b
; coords
[2].z
= f
.l
;
221 coords
[3].x
= -1.0f
; coords
[3].y
= -f
.b
; coords
[3].z
= f
.r
;
224 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
225 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
226 cube_coords_float(rect
, w
, h
, &f
);
228 coords
[0].x
= f
.l
; coords
[0].y
= 1.0f
; coords
[0].z
= f
.t
;
229 coords
[1].x
= f
.r
; coords
[1].y
= 1.0f
; coords
[1].z
= f
.t
;
230 coords
[2].x
= f
.l
; coords
[2].y
= 1.0f
; coords
[2].z
= f
.b
;
231 coords
[3].x
= f
.r
; coords
[3].y
= 1.0f
; coords
[3].z
= f
.b
;
234 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
235 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
236 cube_coords_float(rect
, w
, h
, &f
);
238 coords
[0].x
= f
.l
; coords
[0].y
= -1.0f
; coords
[0].z
= -f
.t
;
239 coords
[1].x
= f
.r
; coords
[1].y
= -1.0f
; coords
[1].z
= -f
.t
;
240 coords
[2].x
= f
.l
; coords
[2].y
= -1.0f
; coords
[2].z
= -f
.b
;
241 coords
[3].x
= f
.r
; coords
[3].y
= -1.0f
; coords
[3].z
= -f
.b
;
244 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
245 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
246 cube_coords_float(rect
, w
, h
, &f
);
248 coords
[0].x
= f
.l
; coords
[0].y
= -f
.t
; coords
[0].z
= 1.0f
;
249 coords
[1].x
= f
.r
; coords
[1].y
= -f
.t
; coords
[1].z
= 1.0f
;
250 coords
[2].x
= f
.l
; coords
[2].y
= -f
.b
; coords
[2].z
= 1.0f
;
251 coords
[3].x
= f
.r
; coords
[3].y
= -f
.b
; coords
[3].z
= 1.0f
;
254 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
255 info
->bind_target
= GL_TEXTURE_CUBE_MAP_ARB
;
256 cube_coords_float(rect
, w
, h
, &f
);
258 coords
[0].x
= -f
.l
; coords
[0].y
= -f
.t
; coords
[0].z
= -1.0f
;
259 coords
[1].x
= -f
.r
; coords
[1].y
= -f
.t
; coords
[1].z
= -1.0f
;
260 coords
[2].x
= -f
.l
; coords
[2].y
= -f
.b
; coords
[2].z
= -1.0f
;
261 coords
[3].x
= -f
.r
; coords
[3].y
= -f
.b
; coords
[3].z
= -1.0f
;
266 static bool fbo_blitter_supported(enum wined3d_blit_op blit_op
, const struct wined3d_gl_info
*gl_info
,
267 const struct wined3d_resource
*src_resource
, DWORD src_location
,
268 const struct wined3d_resource
*dst_resource
, DWORD dst_location
)
270 const struct wined3d_format
*src_format
= src_resource
->format
;
271 const struct wined3d_format
*dst_format
= dst_resource
->format
;
274 if ((wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) || !gl_info
->fbo_ops
.glBlitFramebuffer
)
277 /* Source and/or destination need to be on the GL side. */
278 if (!(src_resource
->access
& dst_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
281 if (src_resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
284 /* We can't copy between depth/stencil and colour attachments. One notable
285 * way we can end up here is when copying between typeless resources with
286 * formats like R16_TYPELESS, which can end up using either a
287 * depth/stencil or a colour format on the OpenGL side, depending on the
288 * resource's bind flags. */
289 src_ds
= src_format
->depth_size
|| src_format
->stencil_size
;
290 dst_ds
= dst_format
->depth_size
|| dst_format
->stencil_size
;
291 if (src_ds
!= dst_ds
)
296 case WINED3D_BLIT_OP_COLOR_BLIT
:
297 if (!((src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_FBO_ATTACHABLE
)
298 || (src_resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)))
300 if (!((dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_FBO_ATTACHABLE
)
301 || (dst_resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)))
303 if ((src_format
->id
!= dst_format
->id
|| dst_location
== WINED3D_LOCATION_DRAWABLE
)
304 && (!is_identity_fixup(src_format
->color_fixup
) || !is_identity_fixup(dst_format
->color_fixup
)))
308 case WINED3D_BLIT_OP_DEPTH_BLIT
:
309 if (!(src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_DEPTH_STENCIL
))
311 if (!(dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_DEPTH_STENCIL
))
313 /* Accept pure swizzle fixups for depth formats. In general we
314 * ignore the stencil component (if present) at the moment and the
315 * swizzle is not relevant with just the depth component. */
316 if (is_complex_fixup(src_format
->color_fixup
) || is_complex_fixup(dst_format
->color_fixup
)
317 || is_scaling_fixup(src_format
->color_fixup
) || is_scaling_fixup(dst_format
->color_fixup
))
328 /* Blit between surface locations. Onscreen on different swapchains is not supported.
329 * Depth / stencil is not supported. Context activation is done by the caller. */
330 static void texture2d_blt_fbo(struct wined3d_device
*device
, struct wined3d_context
*context
,
331 enum wined3d_texture_filter_type filter
, struct wined3d_texture
*src_texture
,
332 unsigned int src_sub_resource_idx
, DWORD src_location
, const RECT
*src_rect
,
333 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, DWORD dst_location
,
334 const RECT
*dst_rect
, const struct wined3d_format
*resolve_format
)
336 struct wined3d_texture
*required_texture
, *restore_texture
= NULL
, *dst_save_texture
= dst_texture
;
337 unsigned int restore_idx
, dst_save_sub_resource_idx
= dst_sub_resource_idx
;
338 struct wined3d_texture
*src_staging_texture
= NULL
;
339 const struct wined3d_gl_info
*gl_info
;
340 struct wined3d_context_gl
*context_gl
;
341 bool resolve
, scaled_resolve
;
346 TRACE("device %p, context %p, filter %s, src_texture %p, src_sub_resource_idx %u, src_location %s, "
347 "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, resolve format %p.\n",
348 device
, context
, debug_d3dtexturefiltertype(filter
), src_texture
, src_sub_resource_idx
,
349 wined3d_debug_location(src_location
), wine_dbgstr_rect(src_rect
), dst_texture
,
350 dst_sub_resource_idx
, wined3d_debug_location(dst_location
), wine_dbgstr_rect(dst_rect
), resolve_format
);
352 resolve
= wined3d_texture_gl_is_multisample_location(wined3d_texture_gl(src_texture
), src_location
);
353 scaled_resolve
= resolve
354 && (abs(src_rect
->bottom
- src_rect
->top
) != abs(dst_rect
->bottom
- dst_rect
->top
)
355 || abs(src_rect
->right
- src_rect
->left
) != abs(dst_rect
->right
- dst_rect
->left
));
357 if (filter
== WINED3D_TEXF_LINEAR
)
358 gl_filter
= scaled_resolve
? GL_SCALED_RESOLVE_NICEST_EXT
: GL_LINEAR
;
360 gl_filter
= scaled_resolve
? GL_SCALED_RESOLVE_FASTEST_EXT
: GL_NEAREST
;
364 GLint resolve_internal
, src_internal
, dst_internal
;
365 enum wined3d_format_id resolve_format_id
;
367 src_internal
= wined3d_gl_get_internal_format(&src_texture
->resource
,
368 wined3d_format_gl(src_texture
->resource
.format
), src_location
== WINED3D_LOCATION_TEXTURE_SRGB
);
369 dst_internal
= wined3d_gl_get_internal_format(&dst_texture
->resource
,
370 wined3d_format_gl(dst_texture
->resource
.format
), dst_location
== WINED3D_LOCATION_TEXTURE_SRGB
);
374 resolve_internal
= wined3d_format_gl(resolve_format
)->internal
;
375 resolve_format_id
= resolve_format
->id
;
377 else if (!wined3d_format_is_typeless(src_texture
->resource
.format
))
379 resolve_internal
= src_internal
;
380 resolve_format_id
= src_texture
->resource
.format
->id
;
384 resolve_internal
= dst_internal
;
385 resolve_format_id
= dst_texture
->resource
.format
->id
;
388 /* In case of typeless resolve the texture type may not match the resolve type.
389 * To handle that, allocate intermediate texture(s) to resolve from/to.
390 * A possible performance improvement would be to resolve using a shader instead. */
391 if (src_internal
!= resolve_internal
)
393 struct wined3d_resource_desc desc
;
397 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
398 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
399 desc
.format
= resolve_format_id
;
400 desc
.multisample_type
= src_texture
->resource
.multisample_type
;
401 desc
.multisample_quality
= src_texture
->resource
.multisample_quality
;
402 desc
.usage
= WINED3DUSAGE_PRIVATE
;
404 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
405 desc
.width
= wined3d_texture_get_level_width(src_texture
, src_level
);
406 desc
.height
= wined3d_texture_get_level_height(src_texture
, src_level
);
410 hr
= wined3d_texture_create(device
, &desc
, 1, 1, 0, NULL
, NULL
, &wined3d_null_parent_ops
,
411 &src_staging_texture
);
414 ERR("Failed to create staging texture, hr %#x.\n", hr
);
418 if (src_location
== WINED3D_LOCATION_DRAWABLE
)
419 FIXME("WINED3D_LOCATION_DRAWABLE not supported for the source of a typeless resolve.\n");
421 device
->blitter
->ops
->blitter_blit(device
->blitter
, WINED3D_BLIT_OP_RAW_BLIT
, context
,
422 src_texture
, src_sub_resource_idx
, src_location
, src_rect
,
423 src_staging_texture
, 0, src_location
, src_rect
,
424 NULL
, WINED3D_TEXF_NONE
, NULL
);
426 src_texture
= src_staging_texture
;
427 src_sub_resource_idx
= 0;
430 if (dst_internal
!= resolve_internal
)
432 struct wined3d_resource_desc desc
;
436 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
437 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
438 desc
.format
= resolve_format_id
;
439 desc
.multisample_type
= dst_texture
->resource
.multisample_type
;
440 desc
.multisample_quality
= dst_texture
->resource
.multisample_quality
;
441 desc
.usage
= WINED3DUSAGE_PRIVATE
;
443 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
444 desc
.width
= wined3d_texture_get_level_width(dst_texture
, dst_level
);
445 desc
.height
= wined3d_texture_get_level_height(dst_texture
, dst_level
);
449 hr
= wined3d_texture_create(device
, &desc
, 1, 1, 0, NULL
, NULL
, &wined3d_null_parent_ops
,
453 ERR("Failed to create staging texture, hr %#x.\n", hr
);
457 wined3d_texture_load_location(dst_texture
, 0, context
, dst_location
);
458 dst_sub_resource_idx
= 0;
462 /* Make sure the locations are up-to-date. Loading the destination
463 * surface isn't required if the entire surface is overwritten. (And is
464 * in fact harmful if we're being called by surface_load_location() with
465 * the purpose of loading the destination surface.) */
466 wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, src_location
);
467 if (!wined3d_texture_is_full_rect(dst_texture
, dst_sub_resource_idx
% dst_texture
->level_count
, dst_rect
))
468 wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
470 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
472 /* Acquire a context for the front-buffer, even though we may be blitting
473 * to/from a back-buffer. Since context_acquire() doesn't take the
474 * resource location into account, it may consider the back-buffer to be
476 if (src_location
== WINED3D_LOCATION_DRAWABLE
)
477 required_texture
= src_texture
->swapchain
->front_buffer
;
478 else if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
479 required_texture
= dst_texture
->swapchain
->front_buffer
;
481 required_texture
= NULL
;
483 restore_texture
= context
->current_rt
.texture
;
484 restore_idx
= context
->current_rt
.sub_resource_idx
;
485 if (restore_texture
!= required_texture
)
486 context
= context_acquire(device
, required_texture
, 0);
488 restore_texture
= NULL
;
490 context_gl
= wined3d_context_gl(context
);
491 if (!context_gl
->valid
)
493 context_release(context
);
494 WARN("Invalid context, skipping blit.\n");
495 restore_texture
= NULL
;
499 gl_info
= context_gl
->gl_info
;
501 if (src_location
== WINED3D_LOCATION_DRAWABLE
)
503 TRACE("Source texture %p is onscreen.\n", src_texture
);
504 buffer
= wined3d_texture_get_gl_buffer(src_texture
);
506 wined3d_texture_translate_drawable_coords(src_texture
, context_gl
->window
, &s
);
511 TRACE("Source texture %p is offscreen.\n", src_texture
);
512 buffer
= GL_COLOR_ATTACHMENT0
;
515 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_READ_FRAMEBUFFER
,
516 &src_texture
->resource
, src_sub_resource_idx
, NULL
, 0, src_location
);
517 gl_info
->gl_ops
.gl
.p_glReadBuffer(buffer
);
518 checkGLcall("glReadBuffer()");
519 wined3d_context_gl_check_fbo_status(context_gl
, GL_READ_FRAMEBUFFER
);
521 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
523 TRACE("Destination texture %p is onscreen.\n", dst_texture
);
524 buffer
= wined3d_texture_get_gl_buffer(dst_texture
);
526 wined3d_texture_translate_drawable_coords(dst_texture
, context_gl
->window
, &d
);
531 TRACE("Destination texture %p is offscreen.\n", dst_texture
);
532 buffer
= GL_COLOR_ATTACHMENT0
;
535 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_DRAW_FRAMEBUFFER
,
536 &dst_texture
->resource
, dst_sub_resource_idx
, NULL
, 0, dst_location
);
537 wined3d_context_gl_set_draw_buffer(context_gl
, buffer
);
538 wined3d_context_gl_check_fbo_status(context_gl
, GL_DRAW_FRAMEBUFFER
);
539 context_invalidate_state(context
, STATE_FRAMEBUFFER
);
541 gl_info
->gl_ops
.gl
.p_glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
542 context_invalidate_state(context
, STATE_BLEND
);
544 gl_info
->gl_ops
.gl
.p_glDisable(GL_SCISSOR_TEST
);
545 context_invalidate_state(context
, STATE_RASTERIZER
);
547 gl_info
->fbo_ops
.glBlitFramebuffer(src_rect
->left
, src_rect
->top
, src_rect
->right
, src_rect
->bottom
,
548 dst_rect
->left
, dst_rect
->top
, dst_rect
->right
, dst_rect
->bottom
, GL_COLOR_BUFFER_BIT
, gl_filter
);
549 checkGLcall("glBlitFramebuffer()");
551 if (dst_location
== WINED3D_LOCATION_DRAWABLE
&& dst_texture
->swapchain
->front_buffer
== dst_texture
)
552 gl_info
->gl_ops
.gl
.p_glFlush();
554 if (dst_texture
!= dst_save_texture
)
556 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
557 FIXME("WINED3D_LOCATION_DRAWABLE not supported for the destination of a typeless resolve.\n");
559 device
->blitter
->ops
->blitter_blit(device
->blitter
, WINED3D_BLIT_OP_RAW_BLIT
, context
,
560 dst_texture
, 0, dst_location
, dst_rect
,
561 dst_save_texture
, dst_save_sub_resource_idx
, dst_location
, dst_rect
,
562 NULL
, WINED3D_TEXF_NONE
, NULL
);
566 if (dst_texture
!= dst_save_texture
)
567 wined3d_texture_decref(dst_texture
);
569 if (src_staging_texture
)
570 wined3d_texture_decref(src_staging_texture
);
573 context_restore(context
, restore_texture
, restore_idx
);
576 static void texture2d_depth_blt_fbo(const struct wined3d_device
*device
, struct wined3d_context
*context
,
577 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, DWORD src_location
,
578 const RECT
*src_rect
, struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
579 DWORD dst_location
, const RECT
*dst_rect
)
581 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
582 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
583 GLbitfield src_mask
, dst_mask
;
586 TRACE("device %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, "
587 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s.\n", device
,
588 src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
), wine_dbgstr_rect(src_rect
),
589 dst_texture
, dst_sub_resource_idx
, wined3d_debug_location(dst_location
), wine_dbgstr_rect(dst_rect
));
592 if (src_texture
->resource
.format
->depth_size
)
593 src_mask
|= GL_DEPTH_BUFFER_BIT
;
594 if (src_texture
->resource
.format
->stencil_size
)
595 src_mask
|= GL_STENCIL_BUFFER_BIT
;
598 if (dst_texture
->resource
.format
->depth_size
)
599 dst_mask
|= GL_DEPTH_BUFFER_BIT
;
600 if (dst_texture
->resource
.format
->stencil_size
)
601 dst_mask
|= GL_STENCIL_BUFFER_BIT
;
603 if (src_mask
!= dst_mask
)
605 ERR("Incompatible formats %s and %s.\n",
606 debug_d3dformat(src_texture
->resource
.format
->id
),
607 debug_d3dformat(dst_texture
->resource
.format
->id
));
613 ERR("Not a depth / stencil format: %s.\n",
614 debug_d3dformat(src_texture
->resource
.format
->id
));
619 /* Make sure the locations are up-to-date. Loading the destination
620 * surface isn't required if the entire surface is overwritten. */
621 wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, src_location
);
622 if (!wined3d_texture_is_full_rect(dst_texture
, dst_sub_resource_idx
% dst_texture
->level_count
, dst_rect
))
623 wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
625 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
627 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_READ_FRAMEBUFFER
, NULL
, 0,
628 &src_texture
->resource
, src_sub_resource_idx
, src_location
);
629 wined3d_context_gl_check_fbo_status(context_gl
, GL_READ_FRAMEBUFFER
);
631 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_DRAW_FRAMEBUFFER
, NULL
, 0,
632 &dst_texture
->resource
, dst_sub_resource_idx
, dst_location
);
633 wined3d_context_gl_set_draw_buffer(context_gl
, GL_NONE
);
634 wined3d_context_gl_check_fbo_status(context_gl
, GL_DRAW_FRAMEBUFFER
);
635 context_invalidate_state(context
, STATE_FRAMEBUFFER
);
637 if (gl_mask
& GL_DEPTH_BUFFER_BIT
)
639 gl_info
->gl_ops
.gl
.p_glDepthMask(GL_TRUE
);
640 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
642 if (gl_mask
& GL_STENCIL_BUFFER_BIT
)
644 if (gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
645 gl_info
->gl_ops
.gl
.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
646 gl_info
->gl_ops
.gl
.p_glStencilMask(~0U);
647 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
650 gl_info
->gl_ops
.gl
.p_glDisable(GL_SCISSOR_TEST
);
651 context_invalidate_state(context
, STATE_RASTERIZER
);
653 gl_info
->fbo_ops
.glBlitFramebuffer(src_rect
->left
, src_rect
->top
, src_rect
->right
, src_rect
->bottom
,
654 dst_rect
->left
, dst_rect
->top
, dst_rect
->right
, dst_rect
->bottom
, gl_mask
, GL_NEAREST
);
655 checkGLcall("glBlitFramebuffer()");
658 static void wined3d_texture_evict_sysmem(struct wined3d_texture
*texture
)
660 struct wined3d_texture_sub_resource
*sub_resource
;
661 unsigned int i
, sub_count
;
663 if (texture
->flags
& (WINED3D_TEXTURE_CONVERTED
| WINED3D_TEXTURE_PIN_SYSMEM
)
664 || texture
->download_count
> WINED3D_TEXTURE_DYNAMIC_MAP_THRESHOLD
)
666 TRACE("Not evicting system memory for texture %p.\n", texture
);
670 TRACE("Evicting system memory for texture %p.\n", texture
);
672 sub_count
= texture
->level_count
* texture
->layer_count
;
673 for (i
= 0; i
< sub_count
; ++i
)
675 sub_resource
= &texture
->sub_resources
[i
];
676 if (sub_resource
->locations
== WINED3D_LOCATION_SYSMEM
)
677 ERR("WINED3D_LOCATION_SYSMEM is the only location for sub-resource %u of texture %p.\n",
679 sub_resource
->locations
&= ~WINED3D_LOCATION_SYSMEM
;
681 wined3d_resource_free_sysmem(&texture
->resource
);
684 void wined3d_texture_validate_location(struct wined3d_texture
*texture
,
685 unsigned int sub_resource_idx
, DWORD location
)
687 struct wined3d_texture_sub_resource
*sub_resource
;
688 DWORD previous_locations
;
690 TRACE("texture %p, sub_resource_idx %u, location %s.\n",
691 texture
, sub_resource_idx
, wined3d_debug_location(location
));
693 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
694 previous_locations
= sub_resource
->locations
;
695 sub_resource
->locations
|= location
;
696 if (previous_locations
== WINED3D_LOCATION_SYSMEM
&& location
!= WINED3D_LOCATION_SYSMEM
697 && !--texture
->sysmem_count
)
698 wined3d_texture_evict_sysmem(texture
);
700 TRACE("New locations flags are %s.\n", wined3d_debug_location(sub_resource
->locations
));
703 static void wined3d_texture_set_dirty(struct wined3d_texture
*texture
)
705 texture
->flags
&= ~(WINED3D_TEXTURE_RGB_VALID
| WINED3D_TEXTURE_SRGB_VALID
);
708 void wined3d_texture_invalidate_location(struct wined3d_texture
*texture
,
709 unsigned int sub_resource_idx
, DWORD location
)
711 struct wined3d_texture_sub_resource
*sub_resource
;
712 DWORD previous_locations
;
714 TRACE("texture %p, sub_resource_idx %u, location %s.\n",
715 texture
, sub_resource_idx
, wined3d_debug_location(location
));
717 if (location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
))
718 wined3d_texture_set_dirty(texture
);
720 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
721 previous_locations
= sub_resource
->locations
;
722 sub_resource
->locations
&= ~location
;
723 if (previous_locations
!= WINED3D_LOCATION_SYSMEM
&& sub_resource
->locations
== WINED3D_LOCATION_SYSMEM
)
724 ++texture
->sysmem_count
;
726 TRACE("New locations flags are %s.\n", wined3d_debug_location(sub_resource
->locations
));
728 if (!sub_resource
->locations
)
729 ERR("Sub-resource %u of texture %p does not have any up to date location.\n",
730 sub_resource_idx
, texture
);
733 void wined3d_texture_clear_dirty_regions(struct wined3d_texture
*texture
)
737 TRACE("texture %p\n", texture
);
739 if (!texture
->dirty_regions
)
742 for (i
= 0; i
< texture
->layer_count
; ++i
)
744 texture
->dirty_regions
[i
].box_count
= 0;
748 static BOOL
wined3d_texture_copy_sysmem_location(struct wined3d_texture
*texture
,
749 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
751 unsigned int size
= texture
->sub_resources
[sub_resource_idx
].size
;
752 struct wined3d_device
*device
= texture
->resource
.device
;
753 const struct wined3d_gl_info
*gl_info
;
754 struct wined3d_bo_gl
*src_bo
, *dst_bo
;
755 struct wined3d_bo_address dst
, src
;
757 if (!wined3d_texture_prepare_location(texture
, sub_resource_idx
, context
, location
))
760 wined3d_texture_get_memory(texture
, sub_resource_idx
, &dst
, location
);
761 wined3d_texture_get_memory(texture
, sub_resource_idx
, &src
,
762 texture
->sub_resources
[sub_resource_idx
].locations
);
764 if ((dst_bo
= (struct wined3d_bo_gl
*)dst
.buffer_object
))
766 context
= context_acquire(device
, NULL
, 0);
767 gl_info
= wined3d_context_gl(context
)->gl_info
;
768 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, dst_bo
->id
));
769 GL_EXTCALL(glBufferSubData(GL_PIXEL_UNPACK_BUFFER
, 0, size
, src
.addr
));
770 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, 0));
771 wined3d_context_gl_reference_bo(wined3d_context_gl(context
), dst_bo
);
772 checkGLcall("PBO upload");
773 context_release(context
);
777 if ((src_bo
= (struct wined3d_bo_gl
*)src
.buffer_object
))
779 context
= context_acquire(device
, NULL
, 0);
780 gl_info
= wined3d_context_gl(context
)->gl_info
;
781 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, src_bo
->id
));
782 GL_EXTCALL(glGetBufferSubData(GL_PIXEL_PACK_BUFFER
, 0, size
, dst
.addr
));
783 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0));
784 wined3d_context_gl_reference_bo(wined3d_context_gl(context
), src_bo
);
785 checkGLcall("PBO download");
786 context_release(context
);
790 memcpy(dst
.addr
, src
.addr
, size
);
794 /* Context activation is done by the caller. Context may be NULL in
795 * WINED3D_NO3D mode. */
796 BOOL
wined3d_texture_load_location(struct wined3d_texture
*texture
,
797 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
799 DWORD current
= texture
->sub_resources
[sub_resource_idx
].locations
;
802 TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
803 texture
, sub_resource_idx
, context
, wined3d_debug_location(location
));
805 TRACE("Current resource location %s.\n", wined3d_debug_location(current
));
807 if (current
& location
)
809 TRACE("Location %s is already up to date.\n", wined3d_debug_location(location
));
815 DWORD required_access
= wined3d_resource_access_from_location(location
);
816 if ((texture
->resource
.access
& required_access
) != required_access
)
817 WARN("Operation requires %#x access, but texture only has %#x.\n",
818 required_access
, texture
->resource
.access
);
821 if (current
& WINED3D_LOCATION_DISCARDED
)
823 TRACE("Sub-resource previously discarded, nothing to do.\n");
824 if (!wined3d_texture_prepare_location(texture
, sub_resource_idx
, context
, location
))
826 wined3d_texture_validate_location(texture
, sub_resource_idx
, location
);
827 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
833 ERR("Sub-resource %u of texture %p does not have any up to date location.\n",
834 sub_resource_idx
, texture
);
835 wined3d_texture_validate_location(texture
, sub_resource_idx
, WINED3D_LOCATION_DISCARDED
);
836 return wined3d_texture_load_location(texture
, sub_resource_idx
, context
, location
);
839 if ((location
& wined3d_texture_sysmem_locations
) && (current
& wined3d_texture_sysmem_locations
))
840 ret
= wined3d_texture_copy_sysmem_location(texture
, sub_resource_idx
, context
, location
);
842 ret
= texture
->texture_ops
->texture_load_location(texture
, sub_resource_idx
, context
, location
);
845 wined3d_texture_validate_location(texture
, sub_resource_idx
, location
);
850 void wined3d_texture_get_memory(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
851 struct wined3d_bo_address
*data
, DWORD locations
)
853 struct wined3d_texture_sub_resource
*sub_resource
;
855 TRACE("texture %p, sub_resource_idx %u, data %p, locations %s.\n",
856 texture
, sub_resource_idx
, data
, wined3d_debug_location(locations
));
858 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
859 if (locations
& WINED3D_LOCATION_BUFFER
)
862 data
->buffer_object
= (uintptr_t)&sub_resource
->bo
;
866 if (locations
& WINED3D_LOCATION_SYSMEM
)
868 if (texture
->sub_resources
[sub_resource_idx
].user_memory
)
870 data
->addr
= texture
->sub_resources
[sub_resource_idx
].user_memory
;
874 data
->addr
= texture
->resource
.heap_memory
;
875 data
->addr
+= sub_resource
->offset
;
877 data
->buffer_object
= 0;
881 ERR("Unexpected locations %s.\n", wined3d_debug_location(locations
));
883 data
->buffer_object
= 0;
886 /* Context activation is done by the caller. */
887 static void wined3d_texture_remove_buffer_object(struct wined3d_texture
*texture
,
888 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
)
890 struct wined3d_bo_gl
*bo
= &texture
->sub_resources
[sub_resource_idx
].bo
;
892 TRACE("texture %p, sub_resource_idx %u, context_gl %p.\n", texture
, sub_resource_idx
, context_gl
);
894 wined3d_context_gl_destroy_bo(context_gl
, bo
);
895 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, WINED3D_LOCATION_BUFFER
);
898 static void wined3d_texture_update_map_binding(struct wined3d_texture
*texture
)
900 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
901 struct wined3d_device
*device
= texture
->resource
.device
;
902 DWORD map_binding
= texture
->update_map_binding
;
903 struct wined3d_context
*context
;
906 context
= context_acquire(device
, NULL
, 0);
908 for (i
= 0; i
< sub_count
; ++i
)
910 if (texture
->sub_resources
[i
].locations
== texture
->resource
.map_binding
911 && !wined3d_texture_load_location(texture
, i
, context
, map_binding
))
912 ERR("Failed to load location %s.\n", wined3d_debug_location(map_binding
));
913 if (texture
->resource
.map_binding
== WINED3D_LOCATION_BUFFER
)
914 wined3d_texture_remove_buffer_object(texture
, i
, wined3d_context_gl(context
));
917 context_release(context
);
919 texture
->resource
.map_binding
= map_binding
;
920 texture
->update_map_binding
= 0;
923 static void wined3d_texture_set_map_binding(struct wined3d_texture
*texture
, DWORD map_binding
)
925 texture
->update_map_binding
= map_binding
;
926 if (!texture
->resource
.map_count
)
927 wined3d_texture_update_map_binding(texture
);
930 /* A GL context is provided by the caller */
931 static void gltexture_delete(struct wined3d_device
*device
, const struct wined3d_gl_info
*gl_info
,
932 struct gl_texture
*tex
)
934 context_gl_resource_released(device
, tex
->name
, FALSE
);
935 gl_info
->gl_ops
.gl
.p_glDeleteTextures(1, &tex
->name
);
939 /* Context activation is done by the caller. */
940 /* The caller is responsible for binding the correct texture. */
941 static void wined3d_texture_gl_allocate_mutable_storage(struct wined3d_texture_gl
*texture_gl
,
942 GLenum gl_internal_format
, const struct wined3d_format_gl
*format
,
943 const struct wined3d_gl_info
*gl_info
)
945 unsigned int level
, level_count
, layer
, layer_count
;
946 GLsizei width
, height
, depth
;
949 level_count
= texture_gl
->t
.level_count
;
950 if (texture_gl
->target
== GL_TEXTURE_1D_ARRAY
|| texture_gl
->target
== GL_TEXTURE_2D_ARRAY
)
953 layer_count
= texture_gl
->t
.layer_count
;
955 for (layer
= 0; layer
< layer_count
; ++layer
)
957 target
= wined3d_texture_gl_get_sub_resource_target(texture_gl
, layer
* level_count
);
959 for (level
= 0; level
< level_count
; ++level
)
961 width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
962 height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
963 if (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_HEIGHT_SCALE
)
965 height
*= format
->f
.height_scale
.numerator
;
966 height
/= format
->f
.height_scale
.denominator
;
969 TRACE("texture_gl %p, layer %u, level %u, target %#x, width %u, height %u.\n",
970 texture_gl
, layer
, level
, target
, width
, height
);
972 if (target
== GL_TEXTURE_3D
|| target
== GL_TEXTURE_2D_ARRAY
)
974 depth
= wined3d_texture_get_level_depth(&texture_gl
->t
, level
);
975 GL_EXTCALL(glTexImage3D(target
, level
, gl_internal_format
, width
, height
,
976 target
== GL_TEXTURE_2D_ARRAY
? texture_gl
->t
.layer_count
: depth
, 0,
977 format
->format
, format
->type
, NULL
));
978 checkGLcall("glTexImage3D");
980 else if (target
== GL_TEXTURE_1D
)
982 gl_info
->gl_ops
.gl
.p_glTexImage1D(target
, level
, gl_internal_format
,
983 width
, 0, format
->format
, format
->type
, NULL
);
987 gl_info
->gl_ops
.gl
.p_glTexImage2D(target
, level
, gl_internal_format
, width
,
988 target
== GL_TEXTURE_1D_ARRAY
? texture_gl
->t
.layer_count
: height
, 0,
989 format
->format
, format
->type
, NULL
);
990 checkGLcall("glTexImage2D");
996 /* Context activation is done by the caller. */
997 /* The caller is responsible for binding the correct texture. */
998 static void wined3d_texture_gl_allocate_immutable_storage(struct wined3d_texture_gl
*texture_gl
,
999 GLenum gl_internal_format
, const struct wined3d_gl_info
*gl_info
)
1001 unsigned int samples
= wined3d_resource_get_sample_count(&texture_gl
->t
.resource
);
1002 GLsizei height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, 0);
1003 GLsizei width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, 0);
1004 GLboolean standard_pattern
= texture_gl
->t
.resource
.multisample_type
!= WINED3D_MULTISAMPLE_NON_MASKABLE
1005 && texture_gl
->t
.resource
.multisample_quality
== WINED3D_STANDARD_MULTISAMPLE_PATTERN
;
1007 switch (texture_gl
->target
)
1010 GL_EXTCALL(glTexStorage3D(texture_gl
->target
, texture_gl
->t
.level_count
,
1011 gl_internal_format
, width
, height
, wined3d_texture_get_level_depth(&texture_gl
->t
, 0)));
1013 case GL_TEXTURE_2D_ARRAY
:
1014 GL_EXTCALL(glTexStorage3D(texture_gl
->target
, texture_gl
->t
.level_count
,
1015 gl_internal_format
, width
, height
, texture_gl
->t
.layer_count
));
1017 case GL_TEXTURE_2D_MULTISAMPLE
:
1018 GL_EXTCALL(glTexStorage2DMultisample(texture_gl
->target
, samples
,
1019 gl_internal_format
, width
, height
, standard_pattern
));
1021 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
1022 GL_EXTCALL(glTexStorage3DMultisample(texture_gl
->target
, samples
,
1023 gl_internal_format
, width
, height
, texture_gl
->t
.layer_count
, standard_pattern
));
1025 case GL_TEXTURE_1D_ARRAY
:
1026 GL_EXTCALL(glTexStorage2D(texture_gl
->target
, texture_gl
->t
.level_count
,
1027 gl_internal_format
, width
, texture_gl
->t
.layer_count
));
1030 GL_EXTCALL(glTexStorage1D(texture_gl
->target
, texture_gl
->t
.level_count
, gl_internal_format
, width
));
1033 GL_EXTCALL(glTexStorage2D(texture_gl
->target
, texture_gl
->t
.level_count
,
1034 gl_internal_format
, width
, height
));
1038 checkGLcall("allocate immutable storage");
1041 void wined3d_texture_sub_resources_destroyed(struct wined3d_texture
*texture
)
1043 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
1044 struct wined3d_texture_sub_resource
*sub_resource
;
1047 for (i
= 0; i
< sub_count
; ++i
)
1049 sub_resource
= &texture
->sub_resources
[i
];
1050 if (sub_resource
->parent
)
1052 TRACE("sub-resource %u.\n", i
);
1053 sub_resource
->parent_ops
->wined3d_object_destroyed(sub_resource
->parent
);
1054 sub_resource
->parent
= NULL
;
1059 static void wined3d_texture_create_dc(void *object
)
1061 const struct wined3d_texture_idx
*idx
= object
;
1062 struct wined3d_context
*context
= NULL
;
1063 unsigned int sub_resource_idx
, level
;
1064 const struct wined3d_format
*format
;
1065 unsigned int row_pitch
, slice_pitch
;
1066 struct wined3d_texture
*texture
;
1067 struct wined3d_dc_info
*dc_info
;
1068 struct wined3d_bo_address data
;
1069 D3DKMT_CREATEDCFROMMEMORY desc
;
1070 struct wined3d_device
*device
;
1073 TRACE("texture %p, sub_resource_idx %u.\n", idx
->texture
, idx
->sub_resource_idx
);
1075 texture
= idx
->texture
;
1076 sub_resource_idx
= idx
->sub_resource_idx
;
1077 level
= sub_resource_idx
% texture
->level_count
;
1078 device
= texture
->resource
.device
;
1080 format
= texture
->resource
.format
;
1081 if (!format
->ddi_format
)
1083 WARN("Cannot create a DC for format %s.\n", debug_d3dformat(format
->id
));
1087 if (!texture
->dc_info
)
1089 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
1091 if (!(texture
->dc_info
= heap_calloc(sub_count
, sizeof(*texture
->dc_info
))))
1093 ERR("Failed to allocate DC info.\n");
1098 if (!(texture
->sub_resources
[sub_resource_idx
].locations
& texture
->resource
.map_binding
))
1100 context
= context_acquire(device
, NULL
, 0);
1101 wined3d_texture_load_location(texture
, sub_resource_idx
, context
, texture
->resource
.map_binding
);
1103 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~texture
->resource
.map_binding
);
1104 wined3d_texture_get_pitch(texture
, level
, &row_pitch
, &slice_pitch
);
1105 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, texture
->resource
.map_binding
);
1106 if (data
.buffer_object
)
1109 context
= context_acquire(device
, NULL
, 0);
1110 desc
.pMemory
= wined3d_context_map_bo_address(context
, &data
,
1111 texture
->sub_resources
[sub_resource_idx
].size
, WINED3D_MAP_READ
| WINED3D_MAP_WRITE
);
1115 desc
.pMemory
= data
.addr
;
1119 context_release(context
);
1121 desc
.Format
= format
->ddi_format
;
1122 desc
.Width
= wined3d_texture_get_level_width(texture
, level
);
1123 desc
.Height
= wined3d_texture_get_level_height(texture
, level
);
1124 desc
.Pitch
= row_pitch
;
1125 desc
.hDeviceDc
= CreateCompatibleDC(NULL
);
1126 desc
.pColorTable
= NULL
;
1128 status
= D3DKMTCreateDCFromMemory(&desc
);
1129 DeleteDC(desc
.hDeviceDc
);
1132 WARN("Failed to create DC, status %#x.\n", status
);
1136 dc_info
= &texture
->dc_info
[sub_resource_idx
];
1137 dc_info
->dc
= desc
.hDc
;
1138 dc_info
->bitmap
= desc
.hBitmap
;
1140 TRACE("Created DC %p, bitmap %p for texture %p, %u.\n", dc_info
->dc
, dc_info
->bitmap
, texture
, sub_resource_idx
);
1143 static void wined3d_texture_destroy_dc(void *object
)
1145 const struct wined3d_texture_idx
*idx
= object
;
1146 D3DKMT_DESTROYDCFROMMEMORY destroy_desc
;
1147 struct wined3d_context
*context
;
1148 struct wined3d_texture
*texture
;
1149 struct wined3d_dc_info
*dc_info
;
1150 struct wined3d_bo_address data
;
1151 unsigned int sub_resource_idx
;
1152 struct wined3d_device
*device
;
1153 struct wined3d_range range
;
1156 TRACE("texture %p, sub_resource_idx %u.\n", idx
->texture
, idx
->sub_resource_idx
);
1158 texture
= idx
->texture
;
1159 sub_resource_idx
= idx
->sub_resource_idx
;
1160 device
= texture
->resource
.device
;
1161 dc_info
= &texture
->dc_info
[sub_resource_idx
];
1165 ERR("Sub-resource {%p, %u} has no DC.\n", texture
, sub_resource_idx
);
1169 TRACE("dc %p, bitmap %p.\n", dc_info
->dc
, dc_info
->bitmap
);
1171 destroy_desc
.hDc
= dc_info
->dc
;
1172 destroy_desc
.hBitmap
= dc_info
->bitmap
;
1173 if ((status
= D3DKMTDestroyDCFromMemory(&destroy_desc
)))
1174 ERR("Failed to destroy dc, status %#x.\n", status
);
1176 dc_info
->bitmap
= NULL
;
1178 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, texture
->resource
.map_binding
);
1179 if (data
.buffer_object
)
1181 context
= context_acquire(device
, NULL
, 0);
1183 range
.size
= texture
->sub_resources
[sub_resource_idx
].size
;
1184 wined3d_context_unmap_bo_address(context
, &data
, 1, &range
);
1185 context_release(context
);
1189 void wined3d_texture_set_swapchain(struct wined3d_texture
*texture
, struct wined3d_swapchain
*swapchain
)
1191 texture
->swapchain
= swapchain
;
1192 wined3d_resource_update_draw_binding(&texture
->resource
);
1195 void wined3d_gl_texture_swizzle_from_color_fixup(GLint swizzle
[4], struct color_fixup_desc fixup
)
1197 static const GLenum swizzle_source
[] =
1199 GL_ZERO
, /* CHANNEL_SOURCE_ZERO */
1200 GL_ONE
, /* CHANNEL_SOURCE_ONE */
1201 GL_RED
, /* CHANNEL_SOURCE_X */
1202 GL_GREEN
, /* CHANNEL_SOURCE_Y */
1203 GL_BLUE
, /* CHANNEL_SOURCE_Z */
1204 GL_ALPHA
, /* CHANNEL_SOURCE_W */
1207 swizzle
[0] = swizzle_source
[fixup
.x_source
];
1208 swizzle
[1] = swizzle_source
[fixup
.y_source
];
1209 swizzle
[2] = swizzle_source
[fixup
.z_source
];
1210 swizzle
[3] = swizzle_source
[fixup
.w_source
];
1213 /* Context activation is done by the caller. */
1214 void wined3d_texture_gl_bind(struct wined3d_texture_gl
*texture_gl
,
1215 struct wined3d_context_gl
*context_gl
, BOOL srgb
)
1217 const struct wined3d_format
*format
= texture_gl
->t
.resource
.format
;
1218 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
1219 const struct color_fixup_desc fixup
= format
->color_fixup
;
1220 struct gl_texture
*gl_tex
;
1223 TRACE("texture_gl %p, context_gl %p, srgb %#x.\n", texture_gl
, context_gl
, srgb
);
1225 if (!needs_separate_srgb_gl_texture(&context_gl
->c
, &texture_gl
->t
))
1228 /* sRGB mode cache for preload() calls outside drawprim. */
1230 texture_gl
->t
.flags
|= WINED3D_TEXTURE_IS_SRGB
;
1232 texture_gl
->t
.flags
&= ~WINED3D_TEXTURE_IS_SRGB
;
1234 gl_tex
= wined3d_texture_gl_get_gl_texture(texture_gl
, srgb
);
1235 target
= texture_gl
->target
;
1239 wined3d_context_gl_bind_texture(context_gl
, target
, gl_tex
->name
);
1243 gl_info
->gl_ops
.gl
.p_glGenTextures(1, &gl_tex
->name
);
1244 checkGLcall("glGenTextures");
1245 TRACE("Generated texture %d.\n", gl_tex
->name
);
1249 ERR("Failed to generate a texture name.\n");
1253 /* Initialise the state of the texture object to the OpenGL defaults, not
1254 * the wined3d defaults. */
1255 gl_tex
->sampler_desc
.address_u
= WINED3D_TADDRESS_WRAP
;
1256 gl_tex
->sampler_desc
.address_v
= WINED3D_TADDRESS_WRAP
;
1257 gl_tex
->sampler_desc
.address_w
= WINED3D_TADDRESS_WRAP
;
1258 memset(gl_tex
->sampler_desc
.border_color
, 0, sizeof(gl_tex
->sampler_desc
.border_color
));
1259 gl_tex
->sampler_desc
.mag_filter
= WINED3D_TEXF_LINEAR
;
1260 gl_tex
->sampler_desc
.min_filter
= WINED3D_TEXF_POINT
; /* GL_NEAREST_MIPMAP_LINEAR */
1261 gl_tex
->sampler_desc
.mip_filter
= WINED3D_TEXF_LINEAR
; /* GL_NEAREST_MIPMAP_LINEAR */
1262 gl_tex
->sampler_desc
.lod_bias
= 0.0f
;
1263 gl_tex
->sampler_desc
.min_lod
= -1000.0f
;
1264 gl_tex
->sampler_desc
.max_lod
= 1000.0f
;
1265 gl_tex
->sampler_desc
.max_anisotropy
= 1;
1266 gl_tex
->sampler_desc
.compare
= FALSE
;
1267 gl_tex
->sampler_desc
.comparison_func
= WINED3D_CMP_LESSEQUAL
;
1268 if (gl_info
->supported
[EXT_TEXTURE_SRGB_DECODE
])
1269 gl_tex
->sampler_desc
.srgb_decode
= TRUE
;
1271 gl_tex
->sampler_desc
.srgb_decode
= srgb
;
1272 gl_tex
->base_level
= 0;
1273 wined3d_texture_set_dirty(&texture_gl
->t
);
1275 wined3d_context_gl_bind_texture(context_gl
, target
, gl_tex
->name
);
1277 /* For a new texture we have to set the texture levels after binding the
1278 * texture. Beware that texture rectangles do not support mipmapping, but
1279 * set the maxmiplevel if we're relying on the partial
1280 * GL_ARB_texture_non_power_of_two emulation with texture rectangles.
1281 * (I.e., do not care about cond_np2 here, just look for
1282 * GL_TEXTURE_RECTANGLE_ARB.) */
1283 if (target
!= GL_TEXTURE_RECTANGLE_ARB
)
1285 TRACE("Setting GL_TEXTURE_MAX_LEVEL to %u.\n", texture_gl
->t
.level_count
- 1);
1286 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MAX_LEVEL
, texture_gl
->t
.level_count
- 1);
1287 checkGLcall("glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, texture->level_count)");
1290 if (target
== GL_TEXTURE_CUBE_MAP_ARB
)
1292 /* Cubemaps are always set to clamp, regardless of the sampler state. */
1293 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1294 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1295 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_R
, GL_CLAMP_TO_EDGE
);
1298 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2
)
1300 /* Conditional non power of two textures use a different clamping
1301 * default. If we're using the GL_WINE_normalized_texrect partial
1302 * driver emulation, we're dealing with a GL_TEXTURE_2D texture which
1303 * has the address mode set to repeat - something that prevents us
1304 * from hitting the accelerated codepath. Thus manually set the GL
1305 * state. The same applies to filtering. Even if the texture has only
1306 * one mip level, the default LINEAR_MIPMAP_LINEAR filter causes a SW
1307 * fallback on macos. */
1308 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
1309 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
1310 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1311 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
1312 checkGLcall("glTexParameteri");
1313 gl_tex
->sampler_desc
.address_u
= WINED3D_TADDRESS_CLAMP
;
1314 gl_tex
->sampler_desc
.address_v
= WINED3D_TADDRESS_CLAMP
;
1315 gl_tex
->sampler_desc
.mag_filter
= WINED3D_TEXF_POINT
;
1316 gl_tex
->sampler_desc
.min_filter
= WINED3D_TEXF_POINT
;
1317 gl_tex
->sampler_desc
.mip_filter
= WINED3D_TEXF_NONE
;
1320 if (gl_info
->supported
[WINED3D_GL_LEGACY_CONTEXT
] && gl_info
->supported
[ARB_DEPTH_TEXTURE
])
1322 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_DEPTH_TEXTURE_MODE_ARB
, GL_INTENSITY
);
1323 checkGLcall("glTexParameteri(GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY)");
1326 if (!is_identity_fixup(fixup
) && can_use_texture_swizzle(context_gl
->c
.d3d_info
, format
))
1330 wined3d_gl_texture_swizzle_from_color_fixup(swizzle
, fixup
);
1331 gl_info
->gl_ops
.gl
.p_glTexParameteriv(target
, GL_TEXTURE_SWIZZLE_RGBA
, swizzle
);
1332 checkGLcall("set format swizzle");
1336 /* Context activation is done by the caller. */
1337 void wined3d_texture_gl_bind_and_dirtify(struct wined3d_texture_gl
*texture_gl
,
1338 struct wined3d_context_gl
*context_gl
, BOOL srgb
)
1340 /* We don't need a specific texture unit, but after binding the texture
1341 * the current unit is dirty. Read the unit back instead of switching to
1342 * 0, this avoids messing around with the state manager's GL states. The
1343 * current texture unit should always be a valid one.
1345 * To be more specific, this is tricky because we can implicitly be
1346 * called from sampler() in state.c. This means we can't touch anything
1347 * other than whatever happens to be the currently active texture, or we
1348 * would risk marking already applied sampler states dirty again. */
1349 if (context_gl
->active_texture
< ARRAY_SIZE(context_gl
->rev_tex_unit_map
))
1351 unsigned int active_sampler
= context_gl
->rev_tex_unit_map
[context_gl
->active_texture
];
1352 if (active_sampler
!= WINED3D_UNMAPPED_STAGE
)
1353 context_invalidate_state(&context_gl
->c
, STATE_SAMPLER(active_sampler
));
1355 /* FIXME: Ideally we'd only do this when touching a binding that's used by
1357 context_invalidate_compute_state(&context_gl
->c
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
1358 context_invalidate_state(&context_gl
->c
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
1360 wined3d_texture_gl_bind(texture_gl
, context_gl
, srgb
);
1363 /* Context activation is done by the caller (state handler). */
1364 /* This function relies on the correct texture being bound and loaded. */
1365 void wined3d_texture_gl_apply_sampler_desc(struct wined3d_texture_gl
*texture_gl
,
1366 const struct wined3d_sampler_desc
*sampler_desc
, const struct wined3d_context_gl
*context_gl
)
1368 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
1369 GLenum target
= texture_gl
->target
;
1370 struct gl_texture
*gl_tex
;
1373 TRACE("texture_gl %p, sampler_desc %p, context_gl %p.\n", texture_gl
, sampler_desc
, context_gl
);
1375 gl_tex
= wined3d_texture_gl_get_gl_texture(texture_gl
, texture_gl
->t
.flags
& WINED3D_TEXTURE_IS_SRGB
);
1377 state
= sampler_desc
->address_u
;
1378 if (state
!= gl_tex
->sampler_desc
.address_u
)
1380 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_S
,
1381 gl_info
->wrap_lookup
[state
- WINED3D_TADDRESS_WRAP
]);
1382 gl_tex
->sampler_desc
.address_u
= state
;
1385 state
= sampler_desc
->address_v
;
1386 if (state
!= gl_tex
->sampler_desc
.address_v
)
1388 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_T
,
1389 gl_info
->wrap_lookup
[state
- WINED3D_TADDRESS_WRAP
]);
1390 gl_tex
->sampler_desc
.address_v
= state
;
1393 state
= sampler_desc
->address_w
;
1394 if (state
!= gl_tex
->sampler_desc
.address_w
)
1396 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_WRAP_R
,
1397 gl_info
->wrap_lookup
[state
- WINED3D_TADDRESS_WRAP
]);
1398 gl_tex
->sampler_desc
.address_w
= state
;
1401 if (memcmp(gl_tex
->sampler_desc
.border_color
, sampler_desc
->border_color
,
1402 sizeof(gl_tex
->sampler_desc
.border_color
)))
1404 gl_info
->gl_ops
.gl
.p_glTexParameterfv(target
, GL_TEXTURE_BORDER_COLOR
, &sampler_desc
->border_color
[0]);
1405 memcpy(gl_tex
->sampler_desc
.border_color
, sampler_desc
->border_color
,
1406 sizeof(gl_tex
->sampler_desc
.border_color
));
1409 state
= sampler_desc
->mag_filter
;
1410 if (state
!= gl_tex
->sampler_desc
.mag_filter
)
1412 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MAG_FILTER
, wined3d_gl_mag_filter(state
));
1413 gl_tex
->sampler_desc
.mag_filter
= state
;
1416 if (sampler_desc
->min_filter
!= gl_tex
->sampler_desc
.min_filter
1417 || sampler_desc
->mip_filter
!= gl_tex
->sampler_desc
.mip_filter
)
1419 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
,
1420 wined3d_gl_min_mip_filter(sampler_desc
->min_filter
, sampler_desc
->mip_filter
));
1421 gl_tex
->sampler_desc
.min_filter
= sampler_desc
->min_filter
;
1422 gl_tex
->sampler_desc
.mip_filter
= sampler_desc
->mip_filter
;
1425 state
= sampler_desc
->max_anisotropy
;
1426 if (state
!= gl_tex
->sampler_desc
.max_anisotropy
)
1428 if (gl_info
->supported
[ARB_TEXTURE_FILTER_ANISOTROPIC
])
1429 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_MAX_ANISOTROPY
, state
);
1431 WARN("Anisotropic filtering not supported.\n");
1432 gl_tex
->sampler_desc
.max_anisotropy
= state
;
1435 if (!sampler_desc
->srgb_decode
!= !gl_tex
->sampler_desc
.srgb_decode
1436 && (context_gl
->c
.d3d_info
->wined3d_creation_flags
& WINED3D_SRGB_READ_WRITE_CONTROL
)
1437 && gl_info
->supported
[EXT_TEXTURE_SRGB_DECODE
])
1439 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_SRGB_DECODE_EXT
,
1440 sampler_desc
->srgb_decode
? GL_DECODE_EXT
: GL_SKIP_DECODE_EXT
);
1441 gl_tex
->sampler_desc
.srgb_decode
= sampler_desc
->srgb_decode
;
1444 if (!sampler_desc
->compare
!= !gl_tex
->sampler_desc
.compare
)
1446 if (sampler_desc
->compare
)
1447 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_COMPARE_MODE_ARB
, GL_COMPARE_R_TO_TEXTURE_ARB
);
1449 gl_info
->gl_ops
.gl
.p_glTexParameteri(target
, GL_TEXTURE_COMPARE_MODE_ARB
, GL_NONE
);
1450 gl_tex
->sampler_desc
.compare
= sampler_desc
->compare
;
1453 checkGLcall("Texture parameter application");
1455 if (gl_info
->supported
[EXT_TEXTURE_LOD_BIAS
])
1457 gl_info
->gl_ops
.gl
.p_glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT
,
1458 GL_TEXTURE_LOD_BIAS_EXT
, sampler_desc
->lod_bias
);
1459 checkGLcall("glTexEnvf(GL_TEXTURE_LOD_BIAS_EXT, ...)");
1463 ULONG CDECL
wined3d_texture_incref(struct wined3d_texture
*texture
)
1467 TRACE("texture %p, swapchain %p.\n", texture
, texture
->swapchain
);
1469 if (texture
->swapchain
)
1470 return wined3d_swapchain_incref(texture
->swapchain
);
1472 refcount
= InterlockedIncrement(&texture
->resource
.ref
);
1473 TRACE("%p increasing refcount to %u.\n", texture
, refcount
);
1478 static void wined3d_texture_destroy_object(void *object
)
1480 struct wined3d_texture
*texture
= object
;
1481 struct wined3d_resource
*resource
;
1482 struct wined3d_dc_info
*dc_info
;
1483 unsigned int sub_count
;
1486 TRACE("texture %p.\n", texture
);
1488 resource
= &texture
->resource
;
1489 sub_count
= texture
->level_count
* texture
->layer_count
;
1491 if ((dc_info
= texture
->dc_info
))
1493 for (i
= 0; i
< sub_count
; ++i
)
1497 struct wined3d_texture_idx texture_idx
= {texture
, i
};
1499 wined3d_texture_destroy_dc(&texture_idx
);
1505 if (texture
->overlay_info
)
1507 for (i
= 0; i
< sub_count
; ++i
)
1509 struct wined3d_overlay_info
*info
= &texture
->overlay_info
[i
];
1510 struct wined3d_overlay_info
*overlay
, *cur
;
1512 list_remove(&info
->entry
);
1513 LIST_FOR_EACH_ENTRY_SAFE(overlay
, cur
, &info
->overlays
, struct wined3d_overlay_info
, entry
)
1515 list_remove(&overlay
->entry
);
1518 heap_free(texture
->overlay_info
);
1521 if (texture
->dirty_regions
)
1523 for (i
= 0; i
< texture
->layer_count
; ++i
)
1525 heap_free(texture
->dirty_regions
[i
].boxes
);
1527 heap_free(texture
->dirty_regions
);
1530 resource
->resource_ops
->resource_unload(resource
);
1533 void wined3d_texture_cleanup(struct wined3d_texture
*texture
)
1535 wined3d_cs_destroy_object(texture
->resource
.device
->cs
, wined3d_texture_destroy_object
, texture
);
1536 resource_cleanup(&texture
->resource
);
1539 static void wined3d_texture_cleanup_sync(struct wined3d_texture
*texture
)
1541 wined3d_texture_sub_resources_destroyed(texture
);
1542 wined3d_texture_cleanup(texture
);
1543 wined3d_resource_wait_idle(&texture
->resource
);
1546 ULONG CDECL
wined3d_texture_decref(struct wined3d_texture
*texture
)
1548 unsigned int i
, sub_resource_count
;
1551 TRACE("texture %p, swapchain %p.\n", texture
, texture
->swapchain
);
1553 if (texture
->swapchain
)
1554 return wined3d_swapchain_decref(texture
->swapchain
);
1556 refcount
= InterlockedDecrement(&texture
->resource
.ref
);
1557 TRACE("%p decreasing refcount to %u.\n", texture
, refcount
);
1561 /* Wait for the texture to become idle if it's using user memory,
1562 * since the application is allowed to free that memory once the
1563 * texture is destroyed. Note that this implies that
1564 * the destroy handler can't access that memory either. */
1565 sub_resource_count
= texture
->layer_count
* texture
->level_count
;
1566 for (i
= 0; i
< sub_resource_count
; ++i
)
1568 if (texture
->sub_resources
[i
].user_memory
)
1570 wined3d_resource_wait_idle(&texture
->resource
);
1574 texture
->resource
.device
->adapter
->adapter_ops
->adapter_destroy_texture(texture
);
1580 struct wined3d_resource
* CDECL
wined3d_texture_get_resource(struct wined3d_texture
*texture
)
1582 TRACE("texture %p.\n", texture
);
1584 return &texture
->resource
;
1587 static BOOL
color_key_equal(const struct wined3d_color_key
*c1
, struct wined3d_color_key
*c2
)
1589 return c1
->color_space_low_value
== c2
->color_space_low_value
1590 && c1
->color_space_high_value
== c2
->color_space_high_value
;
1593 /* Context activation is done by the caller */
1594 void wined3d_texture_load(struct wined3d_texture
*texture
,
1595 struct wined3d_context
*context
, BOOL srgb
)
1597 UINT sub_count
= texture
->level_count
* texture
->layer_count
;
1598 const struct wined3d_d3d_info
*d3d_info
= context
->d3d_info
;
1602 TRACE("texture %p, context %p, srgb %#x.\n", texture
, context
, srgb
);
1604 if (!needs_separate_srgb_gl_texture(context
, texture
))
1608 flag
= WINED3D_TEXTURE_SRGB_VALID
;
1610 flag
= WINED3D_TEXTURE_RGB_VALID
;
1612 if (!d3d_info
->shader_color_key
1613 && (!(texture
->async
.flags
& WINED3D_TEXTURE_ASYNC_COLOR_KEY
)
1614 != !(texture
->async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
1615 || (texture
->async
.flags
& WINED3D_TEXTURE_ASYNC_COLOR_KEY
1616 && !color_key_equal(&texture
->async
.gl_color_key
, &texture
->async
.src_blt_color_key
))))
1618 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
1621 TRACE("Reloading because of color key value change.\n");
1622 for (i
= 0; i
< sub_count
; i
++)
1624 if (!wined3d_texture_load_location(texture
, i
, context
, texture
->resource
.map_binding
))
1625 ERR("Failed to load location %s.\n", wined3d_debug_location(texture
->resource
.map_binding
));
1627 wined3d_texture_invalidate_location(texture
, i
, ~texture
->resource
.map_binding
);
1630 texture
->async
.gl_color_key
= texture
->async
.src_blt_color_key
;
1633 if (texture
->flags
& flag
)
1635 TRACE("Texture %p not dirty, nothing to do.\n", texture
);
1639 /* Reload the surfaces if the texture is marked dirty. */
1640 for (i
= 0; i
< sub_count
; ++i
)
1642 if (!wined3d_texture_load_location(texture
, i
, context
,
1643 srgb
? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
))
1644 ERR("Failed to load location (srgb %#x).\n", srgb
);
1646 texture
->flags
|= flag
;
1649 void * CDECL
wined3d_texture_get_parent(const struct wined3d_texture
*texture
)
1651 TRACE("texture %p.\n", texture
);
1653 return texture
->resource
.parent
;
1656 void CDECL
wined3d_texture_get_pitch(const struct wined3d_texture
*texture
,
1657 unsigned int level
, unsigned int *row_pitch
, unsigned int *slice_pitch
)
1659 const struct wined3d_resource
*resource
= &texture
->resource
;
1660 unsigned int width
= wined3d_texture_get_level_width(texture
, level
);
1661 unsigned int height
= wined3d_texture_get_level_height(texture
, level
);
1663 if (texture
->row_pitch
)
1665 *row_pitch
= texture
->row_pitch
;
1666 *slice_pitch
= texture
->slice_pitch
;
1670 wined3d_format_calculate_pitch(resource
->format
, resource
->device
->surface_alignment
,
1671 width
, height
, row_pitch
, slice_pitch
);
1674 DWORD CDECL
wined3d_texture_set_lod(struct wined3d_texture
*texture
, DWORD lod
)
1676 struct wined3d_resource
*resource
;
1677 DWORD old
= texture
->lod
;
1679 TRACE("texture %p, lod %u.\n", texture
, lod
);
1681 /* The d3d9:texture test shows that SetLOD is ignored on non-managed
1682 * textures. The call always returns 0, and GetLOD always returns 0. */
1683 resource
= &texture
->resource
;
1684 if (!wined3d_resource_access_is_managed(resource
->access
))
1686 TRACE("Ignoring LOD on texture with resource access %s.\n",
1687 wined3d_debug_resource_access(resource
->access
));
1691 if (lod
>= texture
->level_count
)
1692 lod
= texture
->level_count
- 1;
1694 if (texture
->lod
!= lod
)
1696 struct wined3d_device
*device
= resource
->device
;
1698 wined3d_resource_wait_idle(resource
);
1701 wined3d_texture_gl(texture
)->texture_rgb
.base_level
= ~0u;
1702 wined3d_texture_gl(texture
)->texture_srgb
.base_level
= ~0u;
1703 if (resource
->bind_count
)
1704 wined3d_device_context_emit_set_sampler_state(&device
->cs
->c
, texture
->sampler
, WINED3D_SAMP_MAX_MIP_LEVEL
,
1705 device
->cs
->c
.state
->sampler_states
[texture
->sampler
][WINED3D_SAMP_MAX_MIP_LEVEL
]);
1711 DWORD CDECL
wined3d_texture_get_lod(const struct wined3d_texture
*texture
)
1713 TRACE("texture %p, returning %u.\n", texture
, texture
->lod
);
1715 return texture
->lod
;
1718 DWORD CDECL
wined3d_texture_get_level_count(const struct wined3d_texture
*texture
)
1720 TRACE("texture %p, returning %u.\n", texture
, texture
->level_count
);
1722 return texture
->level_count
;
1725 HRESULT CDECL
wined3d_texture_set_color_key(struct wined3d_texture
*texture
,
1726 DWORD flags
, const struct wined3d_color_key
*color_key
)
1728 struct wined3d_device
*device
= texture
->resource
.device
;
1729 static const DWORD all_flags
= WINED3D_CKEY_DST_BLT
| WINED3D_CKEY_DST_OVERLAY
1730 | WINED3D_CKEY_SRC_BLT
| WINED3D_CKEY_SRC_OVERLAY
;
1732 TRACE("texture %p, flags %#x, color_key %p.\n", texture
, flags
, color_key
);
1734 if (flags
& ~all_flags
)
1736 WARN("Invalid flags passed, returning WINED3DERR_INVALIDCALL.\n");
1737 return WINED3DERR_INVALIDCALL
;
1740 wined3d_cs_emit_set_color_key(device
->cs
, texture
, flags
, color_key
);
1745 /* In D3D the depth stencil dimensions have to be greater than or equal to the
1746 * render target dimensions. With FBOs, the dimensions have to be an exact match. */
1747 /* TODO: We should synchronize the renderbuffer's content with the texture's content. */
1748 /* Context activation is done by the caller. */
1749 void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl
*texture_gl
,
1750 struct wined3d_context_gl
*context_gl
, unsigned int level
, const struct wined3d_rendertarget_info
*rt
)
1752 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
1753 struct wined3d_renderbuffer_entry
*entry
;
1754 unsigned int src_width
, src_height
;
1755 unsigned int width
, height
;
1756 GLuint renderbuffer
= 0;
1758 if (gl_info
->supported
[ARB_FRAMEBUFFER_OBJECT
])
1761 if (rt
&& rt
->resource
->format
->id
!= WINED3DFMT_NULL
)
1763 struct wined3d_texture
*rt_texture
;
1764 unsigned int rt_level
;
1766 if (rt
->resource
->type
== WINED3D_RTYPE_BUFFER
)
1768 FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt
->resource
->type
));
1771 rt_texture
= wined3d_texture_from_resource(rt
->resource
);
1772 rt_level
= rt
->sub_resource_idx
% rt_texture
->level_count
;
1774 width
= wined3d_texture_get_level_pow2_width(rt_texture
, rt_level
);
1775 height
= wined3d_texture_get_level_pow2_height(rt_texture
, rt_level
);
1779 width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
1780 height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
1783 src_width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
1784 src_height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
1786 /* A depth stencil smaller than the render target is not valid */
1787 if (width
> src_width
|| height
> src_height
)
1790 /* Remove any renderbuffer set if the sizes match */
1791 if (width
== src_width
&& height
== src_height
)
1793 texture_gl
->current_renderbuffer
= NULL
;
1797 /* Look if we've already got a renderbuffer of the correct dimensions */
1798 LIST_FOR_EACH_ENTRY(entry
, &texture_gl
->renderbuffers
, struct wined3d_renderbuffer_entry
, entry
)
1800 if (entry
->width
== width
&& entry
->height
== height
)
1802 renderbuffer
= entry
->id
;
1803 texture_gl
->current_renderbuffer
= entry
;
1810 const struct wined3d_format_gl
*format_gl
;
1812 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
1813 gl_info
->fbo_ops
.glGenRenderbuffers(1, &renderbuffer
);
1814 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, renderbuffer
);
1815 gl_info
->fbo_ops
.glRenderbufferStorage(GL_RENDERBUFFER
, format_gl
->internal
, width
, height
);
1817 entry
= heap_alloc(sizeof(*entry
));
1818 entry
->width
= width
;
1819 entry
->height
= height
;
1820 entry
->id
= renderbuffer
;
1821 list_add_head(&texture_gl
->renderbuffers
, &entry
->entry
);
1823 texture_gl
->current_renderbuffer
= entry
;
1826 checkGLcall("set compatible renderbuffer");
1829 HRESULT CDECL
wined3d_texture_update_desc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
1830 UINT width
, UINT height
, enum wined3d_format_id format_id
,
1831 enum wined3d_multisample_type multisample_type
, UINT multisample_quality
, void *mem
, UINT pitch
)
1833 struct wined3d_texture_sub_resource
*sub_resource
;
1834 unsigned int i
, level
, sub_resource_count
;
1835 const struct wined3d_d3d_info
*d3d_info
;
1836 const struct wined3d_gl_info
*gl_info
;
1837 const struct wined3d_format
*format
;
1838 struct wined3d_device
*device
;
1839 unsigned int resource_size
;
1840 const struct wined3d
*d3d
;
1841 unsigned int slice_pitch
;
1842 bool update_memory_only
;
1843 bool create_dib
= false;
1845 TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, "
1846 "mem %p, pitch %u, sub_resource_idx %u.\n",
1847 texture
, width
, height
, debug_d3dformat(format_id
), multisample_type
, multisample_quality
, mem
, pitch
,
1850 device
= texture
->resource
.device
;
1851 d3d
= device
->wined3d
;
1852 gl_info
= &device
->adapter
->gl_info
;
1853 d3d_info
= &device
->adapter
->d3d_info
;
1854 format
= wined3d_get_format(device
->adapter
, format_id
, texture
->resource
.bind_flags
);
1855 resource_size
= wined3d_format_calculate_size(format
, device
->surface_alignment
, width
, height
, 1);
1856 level
= sub_resource_idx
% texture
->level_count
;
1857 sub_resource_count
= texture
->level_count
* texture
->layer_count
;
1859 update_memory_only
= width
== wined3d_texture_get_level_width(texture
, level
)
1860 && height
== wined3d_texture_get_level_height(texture
, level
)
1861 && format_id
== texture
->resource
.format
->id
&& multisample_type
== texture
->resource
.multisample_type
1862 && multisample_quality
== texture
->resource
.multisample_quality
;
1865 slice_pitch
= height
* pitch
;
1867 wined3d_format_calculate_pitch(format
, 1, width
, height
, &pitch
, &slice_pitch
);
1869 if (update_memory_only
)
1871 unsigned int current_row_pitch
, current_slice_pitch
;
1873 wined3d_texture_get_pitch(texture
, level
, ¤t_row_pitch
, ¤t_slice_pitch
);
1874 update_memory_only
= pitch
== current_row_pitch
&& slice_pitch
== current_slice_pitch
;
1878 return WINED3DERR_INVALIDCALL
;
1880 if (sub_resource_count
> 1 && !update_memory_only
)
1882 FIXME("Texture has multiple sub-resources, not supported.\n");
1883 return WINED3DERR_INVALIDCALL
;
1886 if (texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
1888 WARN("Not supported on %s.\n", debug_d3dresourcetype(texture
->resource
.type
));
1889 return WINED3DERR_INVALIDCALL
;
1892 if (texture
->resource
.map_count
)
1894 WARN("Texture is mapped.\n");
1895 return WINED3DERR_INVALIDCALL
;
1898 /* We have no way of supporting a pitch that is not a multiple of the pixel
1899 * byte width short of uploading the texture row-by-row.
1900 * Fortunately that's not an issue since D3D9Ex doesn't allow a custom pitch
1901 * for user-memory textures (it always expects packed data) while DirectDraw
1902 * requires a 4-byte aligned pitch and doesn't support texture formats
1903 * larger than 4 bytes per pixel nor any format using 3 bytes per pixel.
1904 * This check is here to verify that the assumption holds. */
1905 if (pitch
% texture
->resource
.format
->byte_count
)
1907 WARN("Pitch unsupported, not a multiple of the texture format byte width.\n");
1908 return WINED3DERR_INVALIDCALL
;
1911 if (device
->d3d_initialized
)
1912 wined3d_cs_emit_unload_resource(device
->cs
, &texture
->resource
);
1913 wined3d_resource_wait_idle(&texture
->resource
);
1915 if (texture
->dc_info
&& texture
->dc_info
[0].dc
)
1917 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
1919 wined3d_cs_destroy_object(device
->cs
, wined3d_texture_destroy_dc
, &texture_idx
);
1920 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
1924 texture
->sub_resources
[sub_resource_idx
].user_memory
= mem
;
1926 if (update_memory_only
)
1928 for (i
= 0; i
< sub_resource_count
; ++i
)
1929 if (!texture
->sub_resources
[i
].user_memory
)
1932 if (i
== sub_resource_count
)
1933 wined3d_resource_free_sysmem(&texture
->resource
);
1937 wined3d_resource_free_sysmem(&texture
->resource
);
1939 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
1941 texture
->row_pitch
= pitch
;
1942 texture
->slice_pitch
= slice_pitch
;
1944 texture
->resource
.format
= format
;
1945 texture
->resource
.multisample_type
= multisample_type
;
1946 texture
->resource
.multisample_quality
= multisample_quality
;
1947 texture
->resource
.width
= width
;
1948 texture
->resource
.height
= height
;
1949 if (!(texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_CPU
) && d3d
->flags
& WINED3D_VIDMEM_ACCOUNTING
)
1950 adapter_adjust_memory(device
->adapter
, (INT64
)texture
->slice_pitch
- texture
->resource
.size
);
1951 texture
->resource
.size
= texture
->slice_pitch
;
1952 sub_resource
->size
= texture
->slice_pitch
;
1953 sub_resource
->locations
= WINED3D_LOCATION_DISCARDED
;
1955 if (texture
->texture_ops
== &texture_gl_ops
)
1957 if (multisample_type
&& gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
1959 wined3d_texture_gl(texture
)->target
= GL_TEXTURE_2D_MULTISAMPLE
;
1960 texture
->flags
&= ~WINED3D_TEXTURE_DOWNLOADABLE
;
1964 wined3d_texture_gl(texture
)->target
= GL_TEXTURE_2D
;
1965 texture
->flags
|= WINED3D_TEXTURE_DOWNLOADABLE
;
1969 if (((width
& (width
- 1)) || (height
& (height
- 1))) && !d3d_info
->texture_npot
1970 && !d3d_info
->texture_npot_conditional
)
1972 texture
->flags
|= WINED3D_TEXTURE_COND_NP2_EMULATED
;
1973 texture
->pow2_width
= texture
->pow2_height
= 1;
1974 while (texture
->pow2_width
< width
)
1975 texture
->pow2_width
<<= 1;
1976 while (texture
->pow2_height
< height
)
1977 texture
->pow2_height
<<= 1;
1981 texture
->flags
&= ~WINED3D_TEXTURE_COND_NP2_EMULATED
;
1982 texture
->pow2_width
= width
;
1983 texture
->pow2_height
= height
;
1987 if (!mem
&& !wined3d_resource_prepare_sysmem(&texture
->resource
))
1988 ERR("Failed to allocate resource memory.\n");
1990 /* The format might be changed to a format that needs conversion.
1991 * If the surface didn't use PBOs previously but could now, don't
1992 * change it - whatever made us not use PBOs might come back, e.g.
1994 if (texture
->resource
.map_binding
== WINED3D_LOCATION_BUFFER
&& !wined3d_texture_use_pbo(texture
, gl_info
))
1995 texture
->resource
.map_binding
= WINED3D_LOCATION_SYSMEM
;
1997 wined3d_texture_validate_location(texture
, sub_resource_idx
, WINED3D_LOCATION_SYSMEM
);
1998 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~WINED3D_LOCATION_SYSMEM
);
2002 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
2004 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
2005 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
2011 /* Context activation is done by the caller. */
2012 static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl
*texture_gl
,
2013 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
)
2015 struct wined3d_texture_sub_resource
*sub_resource
;
2016 struct wined3d_bo_gl
*bo
;
2018 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
2019 bo
= &sub_resource
->bo
;
2023 if (!wined3d_context_gl_create_bo(context_gl
, sub_resource
->size
, GL_PIXEL_UNPACK_BUFFER
,
2024 GL_STREAM_DRAW
, true, GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
| GL_CLIENT_STORAGE_BIT
, bo
))
2027 TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo
->id
, texture_gl
, sub_resource_idx
);
2030 static void wined3d_texture_force_reload(struct wined3d_texture
*texture
)
2032 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
2035 texture
->flags
&= ~(WINED3D_TEXTURE_RGB_ALLOCATED
| WINED3D_TEXTURE_SRGB_ALLOCATED
2036 | WINED3D_TEXTURE_CONVERTED
);
2037 texture
->async
.flags
&= ~WINED3D_TEXTURE_ASYNC_COLOR_KEY
;
2038 for (i
= 0; i
< sub_count
; ++i
)
2040 wined3d_texture_invalidate_location(texture
, i
,
2041 WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
2045 /* Context activation is done by the caller. */
2046 void wined3d_texture_gl_prepare_texture(struct wined3d_texture_gl
*texture_gl
,
2047 struct wined3d_context_gl
*context_gl
, BOOL srgb
)
2049 DWORD alloc_flag
= srgb
? WINED3D_TEXTURE_SRGB_ALLOCATED
: WINED3D_TEXTURE_RGB_ALLOCATED
;
2050 const struct wined3d_d3d_info
*d3d_info
= context_gl
->c
.d3d_info
;
2051 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2052 struct wined3d_resource
*resource
= &texture_gl
->t
.resource
;
2053 const struct wined3d_device
*device
= resource
->device
;
2054 const struct wined3d_format
*format
= resource
->format
;
2055 const struct wined3d_color_key_conversion
*conversion
;
2056 const struct wined3d_format_gl
*format_gl
;
2059 TRACE("texture_gl %p, context_gl %p, format %s.\n", texture_gl
, context_gl
, debug_d3dformat(format
->id
));
2061 if (!d3d_info
->shader_color_key
2062 && !(texture_gl
->t
.async
.flags
& WINED3D_TEXTURE_ASYNC_COLOR_KEY
)
2063 != !(texture_gl
->t
.async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
2065 wined3d_texture_force_reload(&texture_gl
->t
);
2067 if (texture_gl
->t
.async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
2068 texture_gl
->t
.async
.flags
|= WINED3D_TEXTURE_ASYNC_COLOR_KEY
;
2071 if (texture_gl
->t
.flags
& alloc_flag
)
2074 if (resource
->format_flags
& WINED3DFMT_FLAG_DECOMPRESS
)
2076 TRACE("WINED3DFMT_FLAG_DECOMPRESS set.\n");
2077 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2078 format
= wined3d_resource_get_decompress_format(resource
);
2080 else if (format
->conv_byte_count
)
2082 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2084 else if ((conversion
= wined3d_format_get_color_key_conversion(&texture_gl
->t
, TRUE
)))
2086 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2087 format
= wined3d_get_format(device
->adapter
, conversion
->dst_format
, resource
->bind_flags
);
2088 TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format
->id
));
2090 format_gl
= wined3d_format_gl(format
);
2092 wined3d_texture_gl_bind_and_dirtify(texture_gl
, context_gl
, srgb
);
2094 internal
= wined3d_gl_get_internal_format(resource
, format_gl
, srgb
);
2096 FIXME("No GL internal format for format %s.\n", debug_d3dformat(format
->id
));
2098 TRACE("internal %#x, format %#x, type %#x.\n", internal
, format_gl
->format
, format_gl
->type
);
2100 if (wined3d_texture_use_immutable_storage(&texture_gl
->t
, gl_info
))
2101 wined3d_texture_gl_allocate_immutable_storage(texture_gl
, internal
, gl_info
);
2103 wined3d_texture_gl_allocate_mutable_storage(texture_gl
, internal
, format_gl
, gl_info
);
2104 texture_gl
->t
.flags
|= alloc_flag
;
2107 static void wined3d_texture_gl_prepare_rb(struct wined3d_texture_gl
*texture_gl
,
2108 const struct wined3d_gl_info
*gl_info
, BOOL multisample
)
2110 const struct wined3d_format_gl
*format_gl
;
2112 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
2117 if (texture_gl
->rb_multisample
)
2120 samples
= wined3d_resource_get_sample_count(&texture_gl
->t
.resource
);
2122 gl_info
->fbo_ops
.glGenRenderbuffers(1, &texture_gl
->rb_multisample
);
2123 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, texture_gl
->rb_multisample
);
2124 gl_info
->fbo_ops
.glRenderbufferStorageMultisample(GL_RENDERBUFFER
, samples
,
2125 format_gl
->internal
, texture_gl
->t
.resource
.width
, texture_gl
->t
.resource
.height
);
2126 checkGLcall("glRenderbufferStorageMultisample()");
2127 TRACE("Created multisample rb %u.\n", texture_gl
->rb_multisample
);
2131 if (texture_gl
->rb_resolved
)
2134 gl_info
->fbo_ops
.glGenRenderbuffers(1, &texture_gl
->rb_resolved
);
2135 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, texture_gl
->rb_resolved
);
2136 gl_info
->fbo_ops
.glRenderbufferStorage(GL_RENDERBUFFER
, format_gl
->internal
,
2137 texture_gl
->t
.resource
.width
, texture_gl
->t
.resource
.height
);
2138 checkGLcall("glRenderbufferStorage()");
2139 TRACE("Created resolved rb %u.\n", texture_gl
->rb_resolved
);
2143 BOOL
wined3d_texture_prepare_location(struct wined3d_texture
*texture
,
2144 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
2146 return texture
->texture_ops
->texture_prepare_location(texture
, sub_resource_idx
, context
, location
);
2149 static void wined3d_texture_unload_location(struct wined3d_texture
*texture
,
2150 struct wined3d_context
*context
, unsigned int location
)
2152 texture
->texture_ops
->texture_unload_location(texture
, context
, location
);
2155 static struct wined3d_texture_sub_resource
*wined3d_texture_get_sub_resource(struct wined3d_texture
*texture
,
2156 unsigned int sub_resource_idx
)
2158 UINT sub_count
= texture
->level_count
* texture
->layer_count
;
2160 TRACE("texture %p, sub_resource_idx %u.\n", texture
, sub_resource_idx
);
2162 if (sub_resource_idx
>= sub_count
)
2164 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
2168 return &texture
->sub_resources
[sub_resource_idx
];
2171 static void wined3d_texture_dirty_region_add(struct wined3d_texture
*texture
,
2172 unsigned int layer
, const struct wined3d_box
*box
)
2174 struct wined3d_dirty_regions
*regions
;
2177 if (!texture
->dirty_regions
)
2180 regions
= &texture
->dirty_regions
[layer
];
2181 count
= regions
->box_count
+ 1;
2182 if (count
>= WINED3D_MAX_DIRTY_REGION_COUNT
|| !box
2183 || (!box
->left
&& !box
->top
&& !box
->front
2184 && box
->right
== texture
->resource
.width
2185 && box
->bottom
== texture
->resource
.height
2186 && box
->back
== texture
->resource
.depth
))
2188 regions
->box_count
= WINED3D_MAX_DIRTY_REGION_COUNT
;
2192 if (!wined3d_array_reserve((void **)®ions
->boxes
, ®ions
->boxes_size
, count
, sizeof(*regions
->boxes
)))
2194 WARN("Failed to grow boxes array, marking entire texture dirty.\n");
2195 regions
->box_count
= WINED3D_MAX_DIRTY_REGION_COUNT
;
2199 regions
->boxes
[regions
->box_count
++] = *box
;
2202 HRESULT CDECL
wined3d_texture_add_dirty_region(struct wined3d_texture
*texture
,
2203 UINT layer
, const struct wined3d_box
*dirty_region
)
2205 TRACE("texture %p, layer %u, dirty_region %s.\n", texture
, layer
, debug_box(dirty_region
));
2207 if (layer
>= texture
->layer_count
)
2209 WARN("Invalid layer %u specified.\n", layer
);
2210 return WINED3DERR_INVALIDCALL
;
2213 if (dirty_region
&& FAILED(wined3d_resource_check_box_dimensions(&texture
->resource
, 0, dirty_region
)))
2215 WARN("Invalid dirty_region %s specified.\n", debug_box(dirty_region
));
2216 return WINED3DERR_INVALIDCALL
;
2219 wined3d_texture_dirty_region_add(texture
, layer
, dirty_region
);
2220 wined3d_cs_emit_add_dirty_texture_region(texture
->resource
.device
->cs
, texture
, layer
);
2225 static void wined3d_texture_gl_upload_bo(const struct wined3d_format
*src_format
, GLenum target
,
2226 unsigned int level
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
2227 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
, unsigned int update_w
,
2228 unsigned int update_h
, unsigned int update_d
, const BYTE
*addr
, BOOL srgb
,
2229 struct wined3d_texture
*dst_texture
, const struct wined3d_gl_info
*gl_info
)
2231 const struct wined3d_format_gl
*format_gl
= wined3d_format_gl(src_format
);
2233 if (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
2235 GLenum internal
= wined3d_gl_get_internal_format(&dst_texture
->resource
, format_gl
, srgb
);
2236 unsigned int dst_row_pitch
, dst_slice_pitch
;
2238 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
, &dst_row_pitch
, &dst_slice_pitch
);
2240 TRACE("Uploading compressed data, target %#x, level %u, x %u, y %u, z %u, "
2241 "w %u, h %u, d %u, format %#x, image_size %#x, addr %p.\n",
2242 target
, level
, dst_x
, dst_y
, dst_z
, update_w
, update_h
,
2243 update_d
, internal
, dst_slice_pitch
, addr
);
2245 if (target
== GL_TEXTURE_1D
)
2247 GL_EXTCALL(glCompressedTexSubImage1D(target
, level
, dst_x
,
2248 update_w
, internal
, dst_row_pitch
, addr
));
2252 unsigned int row
, y
, slice
, slice_count
= 1, row_count
= 1;
2254 /* glCompressedTexSubImage2D() ignores pixel store state, so we
2255 * can't use the unpack row length like for glTexSubImage2D. */
2256 if (dst_row_pitch
!= src_row_pitch
)
2258 row_count
= (update_h
+ src_format
->block_height
- 1) / src_format
->block_height
;
2259 update_h
= src_format
->block_height
;
2260 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
,
2261 &dst_row_pitch
, &dst_slice_pitch
);
2264 if (dst_slice_pitch
!= src_slice_pitch
)
2266 slice_count
= update_d
;
2270 for (slice
= 0; slice
< slice_count
; ++slice
)
2272 for (row
= 0, y
= dst_y
; row
< row_count
; ++row
)
2274 const BYTE
*upload_addr
= &addr
[slice
* src_slice_pitch
+ row
* src_row_pitch
];
2276 if (target
== GL_TEXTURE_2D_ARRAY
|| target
== GL_TEXTURE_3D
)
2278 GL_EXTCALL(glCompressedTexSubImage3D(target
, level
, dst_x
, y
, dst_z
+ slice
, update_w
,
2279 update_h
, update_d
, internal
, update_d
* dst_slice_pitch
, upload_addr
));
2283 GL_EXTCALL(glCompressedTexSubImage2D(target
, level
, dst_x
, y
, update_w
,
2284 update_h
, internal
, dst_slice_pitch
, upload_addr
));
2287 y
+= src_format
->block_height
;
2291 checkGLcall("Upload compressed texture data");
2295 unsigned int y
, y_count
, z
, z_count
;
2296 bool unpacking_rows
= false;
2298 TRACE("Uploading data, target %#x, level %u, x %u, y %u, z %u, "
2299 "w %u, h %u, d %u, format %#x, type %#x, addr %p.\n",
2300 target
, level
, dst_x
, dst_y
, dst_z
, update_w
, update_h
,
2301 update_d
, format_gl
->format
, format_gl
->type
, addr
);
2303 if (src_row_pitch
&& !(src_row_pitch
% src_format
->byte_count
))
2305 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_ROW_LENGTH
, src_row_pitch
/ src_format
->byte_count
);
2307 unpacking_rows
= true;
2315 if (src_slice_pitch
&& unpacking_rows
&& !(src_slice_pitch
% src_row_pitch
))
2317 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
, src_slice_pitch
/ src_row_pitch
);
2320 else if (src_slice_pitch
&& !unpacking_rows
&& !(src_slice_pitch
% (update_w
* src_format
->byte_count
)))
2322 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
,
2323 src_slice_pitch
/ (update_w
* src_format
->byte_count
));
2332 for (z
= 0; z
< z_count
; ++z
)
2334 for (y
= 0; y
< y_count
; ++y
)
2336 const BYTE
*upload_addr
= &addr
[z
* src_slice_pitch
+ y
* src_row_pitch
];
2337 if (target
== GL_TEXTURE_2D_ARRAY
|| target
== GL_TEXTURE_3D
)
2339 GL_EXTCALL(glTexSubImage3D(target
, level
, dst_x
, dst_y
+ y
, dst_z
+ z
, update_w
,
2340 update_h
, update_d
, format_gl
->format
, format_gl
->type
, upload_addr
));
2342 else if (target
== GL_TEXTURE_1D
)
2344 gl_info
->gl_ops
.gl
.p_glTexSubImage1D(target
, level
, dst_x
,
2345 update_w
, format_gl
->format
, format_gl
->type
, upload_addr
);
2349 gl_info
->gl_ops
.gl
.p_glTexSubImage2D(target
, level
, dst_x
, dst_y
+ y
,
2350 update_w
, update_h
, format_gl
->format
, format_gl
->type
, upload_addr
);
2354 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
2355 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
, 0);
2356 checkGLcall("Upload texture data");
2360 static const struct d3dfmt_alpha_fixup
2362 enum wined3d_format_id format_id
, conv_format_id
;
2364 formats_src_alpha_fixup
[] =
2366 {WINED3DFMT_B8G8R8X8_UNORM
, WINED3DFMT_B8G8R8A8_UNORM
},
2367 {WINED3DFMT_B5G5R5X1_UNORM
, WINED3DFMT_B5G5R5A1_UNORM
},
2368 {WINED3DFMT_B4G4R4X4_UNORM
, WINED3DFMT_B4G4R4A4_UNORM
},
2371 static enum wined3d_format_id
wined3d_get_alpha_fixup_format(enum wined3d_format_id format_id
,
2372 const struct wined3d_format
*dst_format
)
2376 if (!(dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
2377 && !dst_format
->alpha_size
)
2378 return WINED3DFMT_UNKNOWN
;
2380 for (i
= 0; i
< ARRAY_SIZE(formats_src_alpha_fixup
); ++i
)
2382 if (formats_src_alpha_fixup
[i
].format_id
== format_id
)
2383 return formats_src_alpha_fixup
[i
].conv_format_id
;
2386 return WINED3DFMT_UNKNOWN
;
2389 static void wined3d_fixup_alpha(const struct wined3d_format
*format
, const uint8_t *src
,
2390 unsigned int src_row_pitch
, uint8_t *dst
, unsigned int dst_row_pitch
,
2391 unsigned int width
, unsigned int height
)
2393 unsigned int byte_count
, alpha_mask
;
2396 byte_count
= format
->byte_count
;
2397 alpha_mask
= ((1u << format
->alpha_size
) - 1) << format
->alpha_offset
;
2402 for (y
= 0; y
< height
; ++y
)
2404 const uint16_t *src_row
= (const uint16_t *)&src
[y
* src_row_pitch
];
2405 uint16_t *dst_row
= (uint16_t *)&dst
[y
* dst_row_pitch
];
2407 for (x
= 0; x
< width
; ++x
)
2409 dst_row
[x
] = src_row
[x
] | alpha_mask
;
2415 for (y
= 0; y
< height
; ++y
)
2417 const uint32_t *src_row
= (const uint32_t *)&src
[y
* src_row_pitch
];
2418 uint32_t *dst_row
= (uint32_t *)&dst
[y
* dst_row_pitch
];
2420 for (x
= 0; x
< width
; ++x
)
2422 dst_row
[x
] = src_row
[x
] | alpha_mask
;
2428 ERR("Unsupported byte count %u.\n", byte_count
);
2433 static void wined3d_texture_gl_upload_data(struct wined3d_context
*context
,
2434 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
2435 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
2436 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
2437 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
2439 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
2440 enum wined3d_format_id alpha_fixup_format_id
= WINED3DFMT_UNKNOWN
;
2441 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2442 unsigned int update_w
= src_box
->right
- src_box
->left
;
2443 unsigned int update_h
= src_box
->bottom
- src_box
->top
;
2444 unsigned int update_d
= src_box
->back
- src_box
->front
;
2445 struct wined3d_bo_address bo
;
2451 TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, "
2452 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n",
2453 context
, debug_const_bo_address(src_bo_addr
), debug_d3dformat(src_format
->id
), debug_box(src_box
),
2454 src_row_pitch
, src_slice_pitch
, dst_texture
, dst_sub_resource_idx
,
2455 wined3d_debug_location(dst_location
), dst_x
, dst_y
, dst_z
);
2457 if (dst_location
== WINED3D_LOCATION_TEXTURE_SRGB
)
2461 else if (dst_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
2463 FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location
));
2467 wined3d_texture_gl_bind_and_dirtify(wined3d_texture_gl(dst_texture
), wined3d_context_gl(context
), srgb
);
2469 if (dst_texture
->sub_resources
[dst_sub_resource_idx
].map_count
)
2471 WARN("Uploading a texture that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n");
2472 dst_texture
->flags
|= WINED3D_TEXTURE_PIN_SYSMEM
;
2475 if (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_HEIGHT_SCALE
)
2477 update_h
*= src_format
->height_scale
.numerator
;
2478 update_h
/= src_format
->height_scale
.denominator
;
2481 target
= wined3d_texture_gl_get_sub_resource_target(wined3d_texture_gl(dst_texture
), dst_sub_resource_idx
);
2482 level
= dst_sub_resource_idx
% dst_texture
->level_count
;
2486 case GL_TEXTURE_1D_ARRAY
:
2487 dst_y
= dst_sub_resource_idx
/ dst_texture
->level_count
;
2490 case GL_TEXTURE_2D_ARRAY
:
2491 dst_z
= dst_sub_resource_idx
/ dst_texture
->level_count
;
2494 case GL_TEXTURE_2D_MULTISAMPLE
:
2495 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
2496 FIXME("Not supported for multisample textures.\n");
2500 bo
.buffer_object
= src_bo_addr
->buffer_object
;
2501 bo
.addr
= (BYTE
*)src_bo_addr
->addr
+ src_box
->front
* src_slice_pitch
;
2502 if (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_BLOCKS
)
2504 bo
.addr
+= (src_box
->top
/ src_format
->block_height
) * src_row_pitch
;
2505 bo
.addr
+= (src_box
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
2509 bo
.addr
+= src_box
->top
* src_row_pitch
;
2510 bo
.addr
+= src_box
->left
* src_format
->byte_count
;
2513 decompress
= (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_DECOMPRESS
)
2514 || (src_format
->decompress
&& src_format
->id
!= dst_texture
->resource
.format
->id
);
2516 if (src_format
->upload
|| decompress
2517 || (alpha_fixup_format_id
= wined3d_get_alpha_fixup_format(src_format
->id
,
2518 dst_texture
->resource
.format
)) != WINED3DFMT_UNKNOWN
)
2520 const struct wined3d_format
*compressed_format
= src_format
;
2521 unsigned int dst_row_pitch
, dst_slice_pitch
;
2522 struct wined3d_format_gl f
;
2523 void *converted_mem
;
2529 src_format
= wined3d_resource_get_decompress_format(&dst_texture
->resource
);
2531 else if (alpha_fixup_format_id
!= WINED3DFMT_UNKNOWN
)
2533 src_format
= wined3d_get_format(context
->device
->adapter
, alpha_fixup_format_id
, 0);
2534 assert(!!src_format
);
2538 if (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_BLOCKS
)
2539 ERR("Converting a block-based format.\n");
2541 f
= *wined3d_format_gl(src_format
);
2542 f
.f
.byte_count
= src_format
->conv_byte_count
;
2546 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
, &dst_row_pitch
, &dst_slice_pitch
);
2548 if (!(converted_mem
= heap_alloc(dst_slice_pitch
)))
2550 ERR("Failed to allocate upload buffer.\n");
2554 src_mem
= wined3d_context_gl_map_bo_address(context_gl
, &bo
, src_slice_pitch
* update_d
, WINED3D_MAP_READ
);
2556 for (z
= 0; z
< update_d
; ++z
, src_mem
+= src_slice_pitch
)
2559 compressed_format
->decompress(src_mem
, converted_mem
, src_row_pitch
, src_slice_pitch
,
2560 dst_row_pitch
, dst_slice_pitch
, update_w
, update_h
, 1);
2561 else if (alpha_fixup_format_id
!= WINED3DFMT_UNKNOWN
)
2562 wined3d_fixup_alpha(src_format
, src_mem
, src_row_pitch
, converted_mem
, dst_row_pitch
,
2563 update_w
, update_h
);
2565 src_format
->upload(src_mem
, converted_mem
, src_row_pitch
, src_slice_pitch
,
2566 dst_row_pitch
, dst_slice_pitch
, update_w
, update_h
, 1);
2568 wined3d_texture_gl_upload_bo(src_format
, target
, level
, dst_row_pitch
, dst_slice_pitch
, dst_x
,
2569 dst_y
, dst_z
+ z
, update_w
, update_h
, 1, converted_mem
, srgb
, dst_texture
, gl_info
);
2572 wined3d_context_gl_unmap_bo_address(context_gl
, &bo
, 0, NULL
);
2573 heap_free(converted_mem
);
2577 if (bo
.buffer_object
)
2579 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, ((struct wined3d_bo_gl
*)bo
.buffer_object
)->id
));
2580 checkGLcall("glBindBuffer");
2583 wined3d_texture_gl_upload_bo(src_format
, target
, level
, src_row_pitch
, src_slice_pitch
, dst_x
,
2584 dst_y
, dst_z
, update_w
, update_h
, update_d
, bo
.addr
, srgb
, dst_texture
, gl_info
);
2586 if (bo
.buffer_object
)
2588 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, 0));
2589 wined3d_context_gl_reference_bo(context_gl
, (struct wined3d_bo_gl
*)bo
.buffer_object
);
2590 checkGLcall("glBindBuffer");
2594 if (gl_info
->quirks
& WINED3D_QUIRK_FBO_TEX_UPDATE
)
2596 struct wined3d_device
*device
= dst_texture
->resource
.device
;
2599 for (i
= 0; i
< device
->context_count
; ++i
)
2601 wined3d_context_gl_texture_update(wined3d_context_gl(device
->contexts
[i
]), wined3d_texture_gl(dst_texture
));
2606 static void wined3d_texture_gl_download_data_slow_path(struct wined3d_texture_gl
*texture_gl
,
2607 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, const struct wined3d_bo_address
*data
)
2609 struct wined3d_bo_gl
*bo
= (struct wined3d_bo_gl
*)data
->buffer_object
;
2610 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2611 struct wined3d_texture_sub_resource
*sub_resource
;
2612 unsigned int dst_row_pitch
, dst_slice_pitch
;
2613 unsigned int src_row_pitch
, src_slice_pitch
;
2614 const struct wined3d_format_gl
*format_gl
;
2615 BYTE
*temporary_mem
= NULL
;
2620 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
2622 /* Only support read back of converted P8 textures. */
2623 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_CONVERTED
&& format_gl
->f
.id
!= WINED3DFMT_P8_UINT
2624 && !format_gl
->f
.download
)
2626 ERR("Trying to read back converted texture %p, %u with format %s.\n",
2627 texture_gl
, sub_resource_idx
, debug_d3dformat(format_gl
->f
.id
));
2631 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
2632 target
= wined3d_texture_gl_get_sub_resource_target(texture_gl
, sub_resource_idx
);
2633 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
2635 if (target
== GL_TEXTURE_1D_ARRAY
|| target
== GL_TEXTURE_2D_ARRAY
)
2637 if (format_gl
->f
.download
)
2639 FIXME("Reading back converted array texture %p is not supported.\n", texture_gl
);
2643 /* NP2 emulation is not allowed on array textures. */
2644 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2645 ERR("Array texture %p uses NP2 emulation.\n", texture_gl
);
2647 WARN_(d3d_perf
)("Downloading all miplevel layers to get the data for a single sub-resource.\n");
2649 if (!(temporary_mem
= heap_calloc(texture_gl
->t
.layer_count
, sub_resource
->size
)))
2651 ERR("Out of memory.\n");
2656 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2658 if (format_gl
->f
.download
)
2660 FIXME("Reading back converted texture %p with NP2 emulation is not supported.\n", texture_gl
);
2664 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &dst_row_pitch
, &dst_slice_pitch
);
2665 wined3d_format_calculate_pitch(&format_gl
->f
, texture_gl
->t
.resource
.device
->surface_alignment
,
2666 wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
),
2667 wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
),
2668 &src_row_pitch
, &src_slice_pitch
);
2669 if (!(temporary_mem
= heap_alloc(src_slice_pitch
)))
2671 ERR("Out of memory.\n");
2676 ERR("NP2 emulated texture uses PBO unexpectedly.\n");
2677 if (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2678 ERR("Unexpected compressed format for NP2 emulated texture.\n");
2681 if (format_gl
->f
.download
)
2683 struct wined3d_format f
;
2686 ERR("Converted texture %p uses PBO unexpectedly.\n", texture_gl
);
2688 WARN_(d3d_perf
)("Downloading converted texture %p, %u with format %s.\n",
2689 texture_gl
, sub_resource_idx
, debug_d3dformat(format_gl
->f
.id
));
2692 f
.byte_count
= format_gl
->f
.conv_byte_count
;
2693 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &dst_row_pitch
, &dst_slice_pitch
);
2694 wined3d_format_calculate_pitch(&f
, texture_gl
->t
.resource
.device
->surface_alignment
,
2695 wined3d_texture_get_level_width(&texture_gl
->t
, level
),
2696 wined3d_texture_get_level_height(&texture_gl
->t
, level
),
2697 &src_row_pitch
, &src_slice_pitch
);
2699 if (!(temporary_mem
= heap_alloc(src_slice_pitch
)))
2701 ERR("Failed to allocate memory.\n");
2708 mem
= temporary_mem
;
2712 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, bo
->id
));
2713 checkGLcall("glBindBuffer");
2721 if (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2723 TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2724 texture_gl
, sub_resource_idx
, level
, format_gl
->format
, format_gl
->type
, mem
);
2726 GL_EXTCALL(glGetCompressedTexImage(target
, level
, mem
));
2727 checkGLcall("glGetCompressedTexImage");
2731 TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2732 texture_gl
, sub_resource_idx
, level
, format_gl
->format
, format_gl
->type
, mem
);
2734 gl_info
->gl_ops
.gl
.p_glGetTexImage(target
, level
, format_gl
->format
, format_gl
->type
, mem
);
2735 checkGLcall("glGetTexImage");
2738 if (format_gl
->f
.download
)
2740 format_gl
->f
.download(mem
, data
->addr
, src_row_pitch
, src_slice_pitch
, dst_row_pitch
, dst_slice_pitch
,
2741 wined3d_texture_get_level_width(&texture_gl
->t
, level
),
2742 wined3d_texture_get_level_height(&texture_gl
->t
, level
), 1);
2744 else if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2746 const BYTE
*src_data
;
2749 /* Some games (e.g. Warhammer 40,000) don't properly handle texture
2750 * pitches, preventing us from using the texture pitch to box NPOT
2751 * textures. Instead, we repack the texture's CPU copy so that its
2752 * pitch equals bpp * width instead of bpp * pow2width.
2754 * Instead of boxing the texture:
2756 * │<── texture width ──>│ pow2 width ──>│
2757 * ├─────────────────────┼───────────────┼─
2758 * │111111111111111111111│ │ʌ
2759 * │222222222222222222222│ ││
2760 * │333333333333333333333│ padding │texture height
2761 * │444444444444444444444│ ││
2762 * │555555555555555555555│ │v
2763 * ├─────────────────────┘ ├─
2764 * │ │pow2 height
2765 * │ padding padding ││
2767 * └─────────────────────────────────────┴─
2769 * we're repacking the data to the expected texture width
2771 * │<── texture width ──>│ pow2 width ──>│
2772 * ├─────────────────────┴───────────────┼─
2773 * │1111111111111111111112222222222222222│ʌ
2774 * │2222233333333333333333333344444444444││
2775 * │4444444444555555555555555555555 │texture height
2777 * │ padding padding │v
2779 * │ │pow2 height
2780 * │ padding padding ││
2782 * └─────────────────────────────────────┴─
2786 * │<── texture width ──>│
2787 * ├─────────────────────┼─
2788 * │111111111111111111111│ʌ
2789 * │222222222222222222222││
2790 * │333333333333333333333│texture height
2791 * │444444444444444444444││
2792 * │555555555555555555555│v
2793 * └─────────────────────┴─
2795 * This also means that any references to surface memory should work
2796 * with the data as if it were a standard texture with a NPOT width
2797 * instead of a texture boxed up to be a power-of-two texture. */
2799 dst_data
= data
->addr
;
2800 TRACE("Repacking the surface data from pitch %u to pitch %u.\n", src_row_pitch
, dst_row_pitch
);
2801 h
= wined3d_texture_get_level_height(&texture_gl
->t
, level
);
2802 for (y
= 0; y
< h
; ++y
)
2804 memcpy(dst_data
, src_data
, dst_row_pitch
);
2805 src_data
+= src_row_pitch
;
2806 dst_data
+= dst_row_pitch
;
2809 else if (temporary_mem
)
2811 unsigned int layer
= sub_resource_idx
/ texture_gl
->t
.level_count
;
2812 void *src_data
= temporary_mem
+ layer
* sub_resource
->size
;
2815 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, bo
->id
));
2816 checkGLcall("glBindBuffer");
2817 GL_EXTCALL(glBufferSubData(GL_PIXEL_PACK_BUFFER
, 0, sub_resource
->size
, src_data
));
2818 checkGLcall("glBufferSubData");
2822 memcpy(data
->addr
, src_data
, sub_resource
->size
);
2828 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0));
2829 wined3d_context_gl_reference_bo(context_gl
, bo
);
2830 checkGLcall("glBindBuffer");
2833 heap_free(temporary_mem
);
2836 static void wined3d_texture_gl_download_data(struct wined3d_context
*context
,
2837 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
2838 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
2839 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
2840 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
2842 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
2843 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
2844 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2845 unsigned int src_level
, src_width
, src_height
, src_depth
;
2846 unsigned int src_row_pitch
, src_slice_pitch
;
2847 const struct wined3d_format_gl
*format_gl
;
2848 struct wined3d_bo_gl
*dst_bo
;
2852 TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, "
2853 "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n",
2854 context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
2855 debug_box(src_box
), debug_bo_address(dst_bo_addr
), debug_d3dformat(dst_format
->id
),
2856 dst_x
, dst_y
, dst_z
, dst_row_pitch
, dst_slice_pitch
);
2858 if (src_location
== WINED3D_LOCATION_TEXTURE_SRGB
)
2862 else if (src_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
2864 FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location
));
2868 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
2869 src_width
= wined3d_texture_get_level_width(src_texture
, src_level
);
2870 src_height
= wined3d_texture_get_level_height(src_texture
, src_level
);
2871 src_depth
= wined3d_texture_get_level_depth(src_texture
, src_level
);
2872 if (src_box
->left
|| src_box
->top
|| src_box
->right
!= src_width
|| src_box
->bottom
!= src_height
2873 || src_box
->front
|| src_box
->back
!= src_depth
)
2875 FIXME("Unhandled source box %s.\n", debug_box(src_box
));
2879 if (dst_x
|| dst_y
|| dst_z
)
2881 FIXME("Unhandled destination (%u, %u, %u).\n", dst_x
, dst_y
, dst_z
);
2885 if (dst_format
->id
!= src_texture
->resource
.format
->id
)
2887 FIXME("Unhandled format conversion (%s -> %s).\n",
2888 debug_d3dformat(src_texture
->resource
.format
->id
),
2889 debug_d3dformat(dst_format
->id
));
2893 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
2894 if (src_row_pitch
!= dst_row_pitch
|| src_slice_pitch
!= dst_slice_pitch
)
2896 FIXME("Unhandled destination pitches %u/%u (source pitches %u/%u).\n",
2897 dst_row_pitch
, dst_slice_pitch
, src_row_pitch
, src_slice_pitch
);
2901 wined3d_texture_gl_bind_and_dirtify(src_texture_gl
, context_gl
, srgb
);
2903 format_gl
= wined3d_format_gl(src_texture
->resource
.format
);
2904 target
= wined3d_texture_gl_get_sub_resource_target(src_texture_gl
, src_sub_resource_idx
);
2906 if ((src_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_2D
2907 && (target
== GL_TEXTURE_2D_ARRAY
|| format_gl
->f
.conv_byte_count
2908 || src_texture
->flags
& (WINED3D_TEXTURE_CONVERTED
| WINED3D_TEXTURE_COND_NP2_EMULATED
)))
2909 || target
== GL_TEXTURE_1D_ARRAY
)
2911 wined3d_texture_gl_download_data_slow_path(src_texture_gl
, src_sub_resource_idx
, context_gl
, dst_bo_addr
);
2915 if (format_gl
->f
.conv_byte_count
)
2917 FIXME("Attempting to download a converted texture, type %s format %s.\n",
2918 debug_d3dresourcetype(src_texture
->resource
.type
),
2919 debug_d3dformat(format_gl
->f
.id
));
2923 if ((dst_bo
= (struct wined3d_bo_gl
*)dst_bo_addr
->buffer_object
))
2925 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, dst_bo
->id
));
2926 checkGLcall("glBindBuffer");
2929 if (src_texture
->resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2931 TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2932 src_texture
, src_sub_resource_idx
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2934 GL_EXTCALL(glGetCompressedTexImage(target
, src_level
, dst_bo_addr
->addr
));
2935 checkGLcall("glGetCompressedTexImage");
2939 TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2940 src_texture
, src_sub_resource_idx
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2942 gl_info
->gl_ops
.gl
.p_glGetTexImage(target
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2943 checkGLcall("glGetTexImage");
2948 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0));
2949 wined3d_context_gl_reference_bo(context_gl
, dst_bo
);
2950 checkGLcall("glBindBuffer");
2954 /* Context activation is done by the caller. */
2955 static BOOL
wined3d_texture_gl_load_sysmem(struct wined3d_texture_gl
*texture_gl
,
2956 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, DWORD dst_location
)
2958 struct wined3d_texture_sub_resource
*sub_resource
;
2960 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
2962 /* We cannot download data from multisample textures directly. */
2963 if (wined3d_texture_gl_is_multisample_location(texture_gl
, WINED3D_LOCATION_TEXTURE_RGB
))
2965 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_RB_RESOLVED
);
2966 texture2d_read_from_framebuffer(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
,
2967 WINED3D_LOCATION_RB_RESOLVED
, dst_location
);
2971 if (sub_resource
->locations
& (WINED3D_LOCATION_RB_MULTISAMPLE
| WINED3D_LOCATION_RB_RESOLVED
))
2972 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_TEXTURE_RGB
);
2974 /* Download the sub-resource to system memory. */
2975 if (sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
))
2977 unsigned int row_pitch
, slice_pitch
, level
;
2978 struct wined3d_bo_address data
;
2979 struct wined3d_box src_box
;
2980 unsigned int src_location
;
2982 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
2983 wined3d_texture_get_memory(&texture_gl
->t
, sub_resource_idx
, &data
, dst_location
);
2984 src_location
= sub_resource
->locations
& WINED3D_LOCATION_TEXTURE_RGB
2985 ? WINED3D_LOCATION_TEXTURE_RGB
: WINED3D_LOCATION_TEXTURE_SRGB
;
2986 wined3d_texture_get_level_box(&texture_gl
->t
, level
, &src_box
);
2987 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &row_pitch
, &slice_pitch
);
2988 wined3d_texture_gl_download_data(&context_gl
->c
, &texture_gl
->t
, sub_resource_idx
, src_location
,
2989 &src_box
, &data
, texture_gl
->t
.resource
.format
, 0, 0, 0, row_pitch
, slice_pitch
);
2991 ++texture_gl
->t
.download_count
;
2995 if (!(texture_gl
->t
.resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
2996 && (sub_resource
->locations
& WINED3D_LOCATION_DRAWABLE
))
2998 texture2d_read_from_framebuffer(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
,
2999 texture_gl
->t
.resource
.draw_binding
, dst_location
);
3003 FIXME("Can't load texture %p, %u with location flags %s into sysmem.\n",
3004 texture_gl
, sub_resource_idx
, wined3d_debug_location(sub_resource
->locations
));
3009 static BOOL
wined3d_texture_load_drawable(struct wined3d_texture
*texture
,
3010 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
3012 struct wined3d_device
*device
;
3016 if (texture
->resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
3018 DWORD current
= texture
->sub_resources
[sub_resource_idx
].locations
;
3019 FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
3020 wined3d_debug_location(current
));
3024 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
3025 && wined3d_resource_is_offscreen(&texture
->resource
))
3027 ERR("Trying to load offscreen texture into WINED3D_LOCATION_DRAWABLE.\n");
3031 device
= texture
->resource
.device
;
3032 level
= sub_resource_idx
% texture
->level_count
;
3033 SetRect(&r
, 0, 0, wined3d_texture_get_level_width(texture
, level
),
3034 wined3d_texture_get_level_height(texture
, level
));
3035 wined3d_texture_load_location(texture
, sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
3036 device
->blitter
->ops
->blitter_blit(device
->blitter
, WINED3D_BLIT_OP_COLOR_BLIT
, context
,
3037 texture
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &r
,
3038 texture
, sub_resource_idx
, WINED3D_LOCATION_DRAWABLE
, &r
,
3039 NULL
, WINED3D_TEXF_POINT
, NULL
);
3044 static BOOL
wined3d_texture_load_renderbuffer(struct wined3d_texture
*texture
,
3045 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD dst_location
)
3047 unsigned int level
= sub_resource_idx
% texture
->level_count
;
3048 const RECT rect
= {0, 0,
3049 wined3d_texture_get_level_width(texture
, level
),
3050 wined3d_texture_get_level_height(texture
, level
)};
3051 struct wined3d_texture_sub_resource
*sub_resource
;
3052 DWORD src_location
, locations
;
3054 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
3055 locations
= sub_resource
->locations
;
3056 if (texture
->resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
3058 FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
3059 wined3d_debug_location(locations
));
3063 if (locations
& WINED3D_LOCATION_RB_MULTISAMPLE
)
3064 src_location
= WINED3D_LOCATION_RB_MULTISAMPLE
;
3065 else if (locations
& WINED3D_LOCATION_RB_RESOLVED
)
3066 src_location
= WINED3D_LOCATION_RB_RESOLVED
;
3067 else if (locations
& WINED3D_LOCATION_TEXTURE_SRGB
)
3068 src_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
3069 else if (locations
& WINED3D_LOCATION_TEXTURE_RGB
)
3070 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3071 else if (locations
& WINED3D_LOCATION_DRAWABLE
)
3072 src_location
= WINED3D_LOCATION_DRAWABLE
;
3073 else /* texture2d_blt_fbo() will load the source location if necessary. */
3074 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3076 texture2d_blt_fbo(texture
->resource
.device
, context
, WINED3D_TEXF_POINT
, texture
,
3077 sub_resource_idx
, src_location
, &rect
, texture
, sub_resource_idx
, dst_location
, &rect
, NULL
);
3082 static BOOL
wined3d_texture_gl_load_texture(struct wined3d_texture_gl
*texture_gl
,
3083 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, BOOL srgb
)
3085 unsigned int width
, height
, level
, src_row_pitch
, src_slice_pitch
, dst_row_pitch
, dst_slice_pitch
;
3086 struct wined3d_device
*device
= texture_gl
->t
.resource
.device
;
3087 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
3088 const struct wined3d_color_key_conversion
*conversion
;
3089 struct wined3d_texture_sub_resource
*sub_resource
;
3090 const struct wined3d_format
*format
;
3091 struct wined3d_bo_address data
;
3092 BYTE
*src_mem
, *dst_mem
= NULL
;
3093 struct wined3d_box src_box
;
3097 depth
= texture_gl
->t
.resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
;
3098 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
3100 if (!depth
&& wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
3101 && wined3d_resource_is_offscreen(&texture_gl
->t
.resource
)
3102 && (sub_resource
->locations
& WINED3D_LOCATION_DRAWABLE
))
3104 texture2d_load_fb_texture(texture_gl
, sub_resource_idx
, srgb
, &context_gl
->c
);
3109 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
3110 wined3d_texture_get_level_box(&texture_gl
->t
, level
, &src_box
);
3112 if (!depth
&& sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_SRGB
| WINED3D_LOCATION_TEXTURE_RGB
)
3113 && (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB
)
3114 && fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT
, gl_info
,
3115 &texture_gl
->t
.resource
, WINED3D_LOCATION_TEXTURE_RGB
,
3116 &texture_gl
->t
.resource
, WINED3D_LOCATION_TEXTURE_SRGB
))
3120 SetRect(&src_rect
, src_box
.left
, src_box
.top
, src_box
.right
, src_box
.bottom
);
3122 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
,
3123 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &src_rect
,
3124 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_SRGB
, &src_rect
, NULL
);
3126 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
,
3127 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_SRGB
, &src_rect
,
3128 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &src_rect
, NULL
);
3133 if (!depth
&& sub_resource
->locations
& (WINED3D_LOCATION_RB_MULTISAMPLE
| WINED3D_LOCATION_RB_RESOLVED
)
3134 && (!srgb
|| (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB
)))
3136 DWORD src_location
= sub_resource
->locations
& WINED3D_LOCATION_RB_RESOLVED
?
3137 WINED3D_LOCATION_RB_RESOLVED
: WINED3D_LOCATION_RB_MULTISAMPLE
;
3140 SetRect(&src_rect
, src_box
.left
, src_box
.top
, src_box
.right
, src_box
.bottom
);
3141 dst_location
= srgb
? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
3142 if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT
, gl_info
,
3143 &texture_gl
->t
.resource
, src_location
, &texture_gl
->t
.resource
, dst_location
))
3144 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
, &texture_gl
->t
, sub_resource_idx
,
3145 src_location
, &src_rect
, &texture_gl
->t
, sub_resource_idx
, dst_location
, &src_rect
, NULL
);
3150 /* Upload from system memory */
3154 dst_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
3155 if ((sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_RGB
| texture_gl
->t
.resource
.map_binding
))
3156 == WINED3D_LOCATION_TEXTURE_RGB
)
3158 FIXME_(d3d_perf
)("Downloading RGB texture %p, %u to reload it as sRGB.\n", texture_gl
, sub_resource_idx
);
3159 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
,
3160 &context_gl
->c
, texture_gl
->t
.resource
.map_binding
);
3165 dst_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3166 if ((sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_SRGB
| texture_gl
->t
.resource
.map_binding
))
3167 == WINED3D_LOCATION_TEXTURE_SRGB
)
3169 FIXME_(d3d_perf
)("Downloading sRGB texture %p, %u to reload it as RGB.\n", texture_gl
, sub_resource_idx
);
3170 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
,
3171 &context_gl
->c
, texture_gl
->t
.resource
.map_binding
);
3175 if (!(sub_resource
->locations
& wined3d_texture_sysmem_locations
))
3177 WARN("Trying to load a texture from sysmem, but no simple location is valid.\n");
3178 /* Lets hope we get it from somewhere... */
3179 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_SYSMEM
);
3182 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &src_row_pitch
, &src_slice_pitch
);
3184 format
= texture_gl
->t
.resource
.format
;
3185 if ((conversion
= wined3d_format_get_color_key_conversion(&texture_gl
->t
, TRUE
)))
3186 format
= wined3d_get_format(device
->adapter
, conversion
->dst_format
, texture_gl
->t
.resource
.bind_flags
);
3188 /* Don't use PBOs for converted surfaces. During PBO conversion we look at
3189 * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
3190 * getting called. */
3191 if (conversion
&& sub_resource
->bo
.id
)
3193 TRACE("Removing the pbo attached to texture %p, %u.\n", texture_gl
, sub_resource_idx
);
3195 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_SYSMEM
);
3196 wined3d_texture_set_map_binding(&texture_gl
->t
, WINED3D_LOCATION_SYSMEM
);
3199 wined3d_texture_get_memory(&texture_gl
->t
, sub_resource_idx
, &data
, sub_resource
->locations
);
3202 width
= src_box
.right
- src_box
.left
;
3203 height
= src_box
.bottom
- src_box
.top
;
3204 wined3d_format_calculate_pitch(format
, device
->surface_alignment
,
3205 width
, height
, &dst_row_pitch
, &dst_slice_pitch
);
3207 src_mem
= wined3d_context_gl_map_bo_address(context_gl
, &data
, src_slice_pitch
, WINED3D_MAP_READ
);
3208 if (!(dst_mem
= heap_alloc(dst_slice_pitch
)))
3210 ERR("Out of memory (%u).\n", dst_slice_pitch
);
3213 conversion
->convert(src_mem
, src_row_pitch
, dst_mem
, dst_row_pitch
,
3214 width
, height
, &texture_gl
->t
.async
.gl_color_key
);
3215 src_row_pitch
= dst_row_pitch
;
3216 src_slice_pitch
= dst_slice_pitch
;
3217 wined3d_context_gl_unmap_bo_address(context_gl
, &data
, 0, NULL
);
3219 data
.buffer_object
= 0;
3220 data
.addr
= dst_mem
;
3223 wined3d_texture_gl_upload_data(&context_gl
->c
, wined3d_const_bo_address(&data
), format
, &src_box
,
3224 src_row_pitch
, src_slice_pitch
, &texture_gl
->t
, sub_resource_idx
, dst_location
, 0, 0, 0);
3231 static BOOL
wined3d_texture_gl_prepare_location(struct wined3d_texture
*texture
,
3232 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
3234 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3235 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3239 case WINED3D_LOCATION_SYSMEM
:
3240 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
3241 : wined3d_resource_prepare_sysmem(&texture
->resource
);
3243 case WINED3D_LOCATION_BUFFER
:
3244 wined3d_texture_gl_prepare_buffer_object(texture_gl
, sub_resource_idx
, context_gl
);
3247 case WINED3D_LOCATION_TEXTURE_RGB
:
3248 wined3d_texture_gl_prepare_texture(texture_gl
, context_gl
, FALSE
);
3251 case WINED3D_LOCATION_TEXTURE_SRGB
:
3252 wined3d_texture_gl_prepare_texture(texture_gl
, context_gl
, TRUE
);
3255 case WINED3D_LOCATION_DRAWABLE
:
3256 if (!texture
->swapchain
&& wined3d_settings
.offscreen_rendering_mode
!= ORM_BACKBUFFER
)
3257 ERR("Texture %p does not have a drawable.\n", texture
);
3260 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3261 wined3d_texture_gl_prepare_rb(texture_gl
, context_gl
->gl_info
, TRUE
);
3264 case WINED3D_LOCATION_RB_RESOLVED
:
3265 wined3d_texture_gl_prepare_rb(texture_gl
, context_gl
->gl_info
, FALSE
);
3269 ERR("Invalid location %s.\n", wined3d_debug_location(location
));
3274 /* Context activation is done by the caller. */
3275 static BOOL
wined3d_texture_gl_load_location(struct wined3d_texture
*texture
,
3276 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
3278 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3279 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3281 TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
3282 texture
, sub_resource_idx
, context
, wined3d_debug_location(location
));
3284 if (!wined3d_texture_gl_prepare_location(texture
, sub_resource_idx
, context
, location
))
3289 case WINED3D_LOCATION_SYSMEM
:
3290 case WINED3D_LOCATION_BUFFER
:
3291 return wined3d_texture_gl_load_sysmem(texture_gl
, sub_resource_idx
, context_gl
, location
);
3293 case WINED3D_LOCATION_DRAWABLE
:
3294 return wined3d_texture_load_drawable(texture
, sub_resource_idx
, context
);
3296 case WINED3D_LOCATION_RB_RESOLVED
:
3297 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3298 return wined3d_texture_load_renderbuffer(texture
, sub_resource_idx
, context
, location
);
3300 case WINED3D_LOCATION_TEXTURE_RGB
:
3301 case WINED3D_LOCATION_TEXTURE_SRGB
:
3302 return wined3d_texture_gl_load_texture(texture_gl
, sub_resource_idx
,
3303 context_gl
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
3306 FIXME("Unhandled %s load from %s.\n", wined3d_debug_location(location
),
3307 wined3d_debug_location(texture
->sub_resources
[sub_resource_idx
].locations
));
3312 static void wined3d_texture_gl_unload_location(struct wined3d_texture
*texture
,
3313 struct wined3d_context
*context
, unsigned int location
)
3315 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3316 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3317 struct wined3d_renderbuffer_entry
*entry
, *entry2
;
3318 unsigned int i
, sub_count
;
3320 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
3324 case WINED3D_LOCATION_BUFFER
:
3325 sub_count
= texture
->level_count
* texture
->layer_count
;
3326 for (i
= 0; i
< sub_count
; ++i
)
3328 if (texture_gl
->t
.sub_resources
[i
].bo
.id
)
3329 wined3d_texture_remove_buffer_object(&texture_gl
->t
, i
, context_gl
);
3333 case WINED3D_LOCATION_TEXTURE_RGB
:
3334 if (texture_gl
->texture_rgb
.name
)
3335 gltexture_delete(texture_gl
->t
.resource
.device
, context_gl
->gl_info
, &texture_gl
->texture_rgb
);
3338 case WINED3D_LOCATION_TEXTURE_SRGB
:
3339 if (texture_gl
->texture_srgb
.name
)
3340 gltexture_delete(texture_gl
->t
.resource
.device
, context_gl
->gl_info
, &texture_gl
->texture_srgb
);
3343 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3344 if (texture_gl
->rb_multisample
)
3346 TRACE("Deleting multisample renderbuffer %u.\n", texture_gl
->rb_multisample
);
3347 context_gl_resource_released(texture_gl
->t
.resource
.device
, texture_gl
->rb_multisample
, TRUE
);
3348 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &texture_gl
->rb_multisample
);
3349 texture_gl
->rb_multisample
= 0;
3353 case WINED3D_LOCATION_RB_RESOLVED
:
3354 LIST_FOR_EACH_ENTRY_SAFE(entry
, entry2
, &texture_gl
->renderbuffers
,
3355 struct wined3d_renderbuffer_entry
, entry
)
3357 context_gl_resource_released(texture_gl
->t
.resource
.device
, entry
->id
, TRUE
);
3358 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &entry
->id
);
3359 list_remove(&entry
->entry
);
3362 list_init(&texture_gl
->renderbuffers
);
3363 texture_gl
->current_renderbuffer
= NULL
;
3365 if (texture_gl
->rb_resolved
)
3367 TRACE("Deleting resolved renderbuffer %u.\n", texture_gl
->rb_resolved
);
3368 context_gl_resource_released(texture_gl
->t
.resource
.device
, texture_gl
->rb_resolved
, TRUE
);
3369 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &texture_gl
->rb_resolved
);
3370 texture_gl
->rb_resolved
= 0;
3375 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
3380 static const struct wined3d_texture_ops texture_gl_ops
=
3382 wined3d_texture_gl_prepare_location
,
3383 wined3d_texture_gl_load_location
,
3384 wined3d_texture_gl_unload_location
,
3385 wined3d_texture_gl_upload_data
,
3386 wined3d_texture_gl_download_data
,
3389 struct wined3d_texture
* __cdecl
wined3d_texture_from_resource(struct wined3d_resource
*resource
)
3391 return texture_from_resource(resource
);
3394 static ULONG
texture_resource_incref(struct wined3d_resource
*resource
)
3396 return wined3d_texture_incref(texture_from_resource(resource
));
3399 static ULONG
texture_resource_decref(struct wined3d_resource
*resource
)
3401 return wined3d_texture_decref(texture_from_resource(resource
));
3404 static void texture_resource_preload(struct wined3d_resource
*resource
)
3406 struct wined3d_texture
*texture
= texture_from_resource(resource
);
3407 struct wined3d_context
*context
;
3409 context
= context_acquire(resource
->device
, NULL
, 0);
3410 wined3d_texture_load(texture
, context
, texture
->flags
& WINED3D_TEXTURE_IS_SRGB
);
3411 context_release(context
);
3414 static void texture_resource_unload(struct wined3d_resource
*resource
)
3416 struct wined3d_texture
*texture
= texture_from_resource(resource
);
3417 struct wined3d_device
*device
= resource
->device
;
3418 unsigned int location
= resource
->map_binding
;
3419 struct wined3d_context
*context
;
3420 unsigned int sub_count
, i
;
3422 TRACE("resource %p.\n", resource
);
3424 /* D3D is not initialised, so no GPU locations should currently exist.
3425 * Moreover, we may not be able to acquire a valid context. */
3426 if (!device
->d3d_initialized
)
3429 context
= context_acquire(device
, NULL
, 0);
3431 if (location
== WINED3D_LOCATION_BUFFER
)
3432 location
= WINED3D_LOCATION_SYSMEM
;
3434 sub_count
= texture
->level_count
* texture
->layer_count
;
3435 for (i
= 0; i
< sub_count
; ++i
)
3437 if (resource
->access
& WINED3D_RESOURCE_ACCESS_CPU
3438 && wined3d_texture_load_location(texture
, i
, context
, location
))
3440 wined3d_texture_invalidate_location(texture
, i
, ~location
);
3444 if (resource
->access
& WINED3D_RESOURCE_ACCESS_CPU
)
3445 ERR("Discarding %s %p sub-resource %u with resource access %s.\n",
3446 debug_d3dresourcetype(resource
->type
), resource
, i
,
3447 wined3d_debug_resource_access(resource
->access
));
3448 wined3d_texture_validate_location(texture
, i
, WINED3D_LOCATION_DISCARDED
);
3449 wined3d_texture_invalidate_location(texture
, i
, ~WINED3D_LOCATION_DISCARDED
);
3453 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_BUFFER
);
3454 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
3455 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_TEXTURE_SRGB
);
3456 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_RB_MULTISAMPLE
);
3457 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_RB_RESOLVED
);
3459 context_release(context
);
3461 wined3d_texture_force_reload(texture
);
3462 if (texture
->resource
.bind_count
)
3463 device_invalidate_state(device
, STATE_SAMPLER(texture
->sampler
));
3464 wined3d_texture_set_dirty(texture
);
3466 resource_unload(&texture
->resource
);
3469 static HRESULT
texture_resource_sub_resource_get_desc(struct wined3d_resource
*resource
,
3470 unsigned int sub_resource_idx
, struct wined3d_sub_resource_desc
*desc
)
3472 const struct wined3d_texture
*texture
= texture_from_resource(resource
);
3474 return wined3d_texture_get_sub_resource_desc(texture
, sub_resource_idx
, desc
);
3477 static void texture_resource_sub_resource_get_map_pitch(struct wined3d_resource
*resource
,
3478 unsigned int sub_resource_idx
, unsigned int *row_pitch
, unsigned int *slice_pitch
)
3480 const struct wined3d_texture
*texture
= texture_from_resource(resource
);
3481 unsigned int level
= sub_resource_idx
% texture
->level_count
;
3483 if (resource
->format_flags
& WINED3DFMT_FLAG_BROKEN_PITCH
)
3485 *row_pitch
= wined3d_texture_get_level_width(texture
, level
) * resource
->format
->byte_count
;
3486 *slice_pitch
= wined3d_texture_get_level_height(texture
, level
) * (*row_pitch
);
3490 wined3d_texture_get_pitch(texture
, level
, row_pitch
, slice_pitch
);
3494 static HRESULT
texture_resource_sub_resource_map(struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
3495 void **map_ptr
, const struct wined3d_box
*box
, DWORD flags
)
3497 const struct wined3d_format
*format
= resource
->format
;
3498 struct wined3d_texture_sub_resource
*sub_resource
;
3499 struct wined3d_device
*device
= resource
->device
;
3500 unsigned int fmt_flags
= resource
->format_flags
;
3501 unsigned int row_pitch
, slice_pitch
;
3502 struct wined3d_context
*context
;
3503 struct wined3d_texture
*texture
;
3504 struct wined3d_bo_address data
;
3505 unsigned int texture_level
;
3509 TRACE("resource %p, sub_resource_idx %u, map_ptr %p, box %s, flags %#x.\n",
3510 resource
, sub_resource_idx
, map_ptr
, debug_box(box
), flags
);
3512 texture
= texture_from_resource(resource
);
3513 sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
);
3515 texture_level
= sub_resource_idx
% texture
->level_count
;
3517 if (texture
->flags
& WINED3D_TEXTURE_DC_IN_USE
)
3519 WARN("DC is in use.\n");
3520 return WINED3DERR_INVALIDCALL
;
3523 if (sub_resource
->map_count
)
3525 WARN("Sub-resource is already mapped.\n");
3526 return WINED3DERR_INVALIDCALL
;
3529 context
= context_acquire(device
, NULL
, 0);
3531 if (flags
& WINED3D_MAP_DISCARD
)
3533 TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n",
3534 wined3d_debug_location(resource
->map_binding
));
3535 if ((ret
= wined3d_texture_prepare_location(texture
, sub_resource_idx
, context
, resource
->map_binding
)))
3536 wined3d_texture_validate_location(texture
, sub_resource_idx
, resource
->map_binding
);
3540 if (resource
->usage
& WINED3DUSAGE_DYNAMIC
)
3541 WARN_(d3d_perf
)("Mapping a dynamic texture without WINED3D_MAP_DISCARD.\n");
3542 ret
= wined3d_texture_load_location(texture
, sub_resource_idx
, context
, resource
->map_binding
);
3547 ERR("Failed to prepare location.\n");
3548 context_release(context
);
3549 return E_OUTOFMEMORY
;
3552 /* We only record dirty regions for the top-most level. */
3553 if (texture
->dirty_regions
&& flags
& WINED3D_MAP_WRITE
3554 && !(flags
& WINED3D_MAP_NO_DIRTY_UPDATE
) && !texture_level
)
3555 wined3d_texture_dirty_region_add(texture
, sub_resource_idx
/ texture
->level_count
, box
);
3557 if (flags
& WINED3D_MAP_WRITE
3558 && (!(flags
& WINED3D_MAP_NO_DIRTY_UPDATE
) || (resource
->usage
& WINED3DUSAGE_DYNAMIC
)))
3559 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~resource
->map_binding
);
3561 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, resource
->map_binding
);
3562 base_memory
= wined3d_context_map_bo_address(context
, &data
, sub_resource
->size
, flags
);
3563 sub_resource
->map_flags
= flags
;
3564 TRACE("Base memory pointer %p.\n", base_memory
);
3566 context_release(context
);
3568 texture_resource_sub_resource_get_map_pitch(resource
, sub_resource_idx
, &row_pitch
, &slice_pitch
);
3570 if ((fmt_flags
& (WINED3DFMT_FLAG_BLOCKS
| WINED3DFMT_FLAG_BROKEN_PITCH
)) == WINED3DFMT_FLAG_BLOCKS
)
3572 /* Compressed textures are block based, so calculate the offset of
3573 * the block that contains the top-left pixel of the mapped box. */
3574 *map_ptr
= base_memory
3575 + (box
->front
* slice_pitch
)
3576 + ((box
->top
/ format
->block_height
) * row_pitch
)
3577 + ((box
->left
/ format
->block_width
) * format
->block_byte_count
);
3581 *map_ptr
= base_memory
3582 + (box
->front
* slice_pitch
)
3583 + (box
->top
* row_pitch
)
3584 + (box
->left
* format
->byte_count
);
3587 if (texture
->swapchain
&& texture
->swapchain
->front_buffer
== texture
)
3589 RECT
*r
= &texture
->swapchain
->front_buffer_update
;
3591 SetRect(r
, box
->left
, box
->top
, box
->right
, box
->bottom
);
3592 TRACE("Mapped front buffer %s.\n", wine_dbgstr_rect(r
));
3595 ++resource
->map_count
;
3596 ++sub_resource
->map_count
;
3598 TRACE("Returning memory %p.\n", *map_ptr
);
3603 static HRESULT
texture_resource_sub_resource_unmap(struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
3605 struct wined3d_texture_sub_resource
*sub_resource
;
3606 struct wined3d_device
*device
= resource
->device
;
3607 struct wined3d_context
*context
;
3608 struct wined3d_texture
*texture
;
3609 struct wined3d_bo_address data
;
3610 struct wined3d_range range
;
3612 TRACE("resource %p, sub_resource_idx %u.\n", resource
, sub_resource_idx
);
3614 texture
= texture_from_resource(resource
);
3615 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
3616 return E_INVALIDARG
;
3618 if (!sub_resource
->map_count
)
3620 WARN("Trying to unmap unmapped sub-resource.\n");
3621 if (texture
->flags
& WINED3D_TEXTURE_DC_IN_USE
)
3623 return WINEDDERR_NOTLOCKED
;
3626 context
= context_acquire(device
, NULL
, 0);
3628 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, texture
->resource
.map_binding
);
3630 range
.size
= sub_resource
->size
;
3631 wined3d_context_unmap_bo_address(context
, &data
, !!(sub_resource
->map_flags
& WINED3D_MAP_WRITE
), &range
);
3633 context_release(context
);
3635 if (texture
->swapchain
&& texture
->swapchain
->front_buffer
== texture
)
3637 if (!(sub_resource
->locations
& (WINED3D_LOCATION_DRAWABLE
| WINED3D_LOCATION_TEXTURE_RGB
)))
3638 texture
->swapchain
->swapchain_ops
->swapchain_frontbuffer_updated(texture
->swapchain
);
3641 --sub_resource
->map_count
;
3642 if (!--resource
->map_count
&& texture
->update_map_binding
)
3643 wined3d_texture_update_map_binding(texture
);
3648 static const struct wined3d_resource_ops texture_resource_ops
=
3650 texture_resource_incref
,
3651 texture_resource_decref
,
3652 texture_resource_preload
,
3653 texture_resource_unload
,
3654 texture_resource_sub_resource_get_desc
,
3655 texture_resource_sub_resource_get_map_pitch
,
3656 texture_resource_sub_resource_map
,
3657 texture_resource_sub_resource_unmap
,
3660 static HRESULT
wined3d_texture_init(struct wined3d_texture
*texture
, const struct wined3d_resource_desc
*desc
,
3661 unsigned int layer_count
, unsigned int level_count
, DWORD flags
, struct wined3d_device
*device
,
3662 void *parent
, const struct wined3d_parent_ops
*parent_ops
, void *sub_resources
,
3663 const struct wined3d_texture_ops
*texture_ops
)
3665 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3666 struct wined3d_device_parent
*device_parent
= device
->device_parent
;
3667 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
3668 unsigned int sub_count
, i
, j
, size
, offset
= 0;
3669 unsigned int pow2_width
, pow2_height
;
3670 const struct wined3d_format
*format
;
3673 TRACE("texture %p, resource_type %s, format %s, multisample_type %#x, multisample_quality %#x, "
3674 "usage %s, access %s, width %u, height %u, depth %u, layer_count %u, level_count %u, "
3675 "flags %#x, device %p, parent %p, parent_ops %p, sub_resources %p, texture_ops %p.\n",
3676 texture
, debug_d3dresourcetype(desc
->resource_type
), debug_d3dformat(desc
->format
),
3677 desc
->multisample_type
, desc
->multisample_quality
, debug_d3dusage(desc
->usage
),
3678 wined3d_debug_resource_access(desc
->access
), desc
->width
, desc
->height
, desc
->depth
,
3679 layer_count
, level_count
, flags
, device
, parent
, parent_ops
, sub_resources
, texture_ops
);
3681 if (!desc
->width
|| !desc
->height
|| !desc
->depth
)
3682 return WINED3DERR_INVALIDCALL
;
3684 if (desc
->resource_type
== WINED3D_RTYPE_TEXTURE_3D
&& layer_count
!= 1)
3686 ERR("Invalid layer count for volume texture.\n");
3687 return E_INVALIDARG
;
3690 texture
->sub_resources
= sub_resources
;
3692 /* TODO: It should only be possible to create textures for formats
3693 * that are reported as supported. */
3694 if (WINED3DFMT_UNKNOWN
>= desc
->format
)
3696 WARN("Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n");
3697 return WINED3DERR_INVALIDCALL
;
3699 format
= wined3d_get_format(device
->adapter
, desc
->format
, desc
->bind_flags
);
3701 if (desc
->usage
& WINED3DUSAGE_DYNAMIC
&& (wined3d_resource_access_is_managed(desc
->access
)
3702 || desc
->usage
& WINED3DUSAGE_SCRATCH
))
3704 WARN("Attempted to create a dynamic texture with access %s and usage %s.\n",
3705 wined3d_debug_resource_access(desc
->access
), debug_d3dusage(desc
->usage
));
3706 return WINED3DERR_INVALIDCALL
;
3709 pow2_width
= desc
->width
;
3710 pow2_height
= desc
->height
;
3711 if (((desc
->width
& (desc
->width
- 1)) || (desc
->height
& (desc
->height
- 1)) || (desc
->depth
& (desc
->depth
- 1)))
3712 && !d3d_info
->texture_npot
)
3714 /* level_count == 0 returns an error as well. */
3715 if (level_count
!= 1 || layer_count
!= 1 || desc
->resource_type
== WINED3D_RTYPE_TEXTURE_3D
)
3717 if (!(desc
->usage
& WINED3DUSAGE_SCRATCH
))
3719 WARN("Attempted to create a mipmapped/cube/array/volume NPOT "
3720 "texture without unconditional NPOT support.\n");
3721 return WINED3DERR_INVALIDCALL
;
3724 WARN("Creating a scratch mipmapped/cube/array NPOT texture despite lack of HW support.\n");
3726 texture
->flags
|= WINED3D_TEXTURE_COND_NP2
;
3728 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
&& !d3d_info
->texture_npot_conditional
)
3730 /* TODO: Add support for non-power-of-two compressed textures. */
3731 if (format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
]
3732 & (WINED3DFMT_FLAG_COMPRESSED
| WINED3DFMT_FLAG_HEIGHT_SCALE
))
3734 FIXME("Compressed or height scaled non-power-of-two (%ux%u) textures are not supported.\n",
3735 desc
->width
, desc
->height
);
3736 return WINED3DERR_NOTAVAILABLE
;
3739 /* Find the nearest pow2 match. */
3740 pow2_width
= pow2_height
= 1;
3741 while (pow2_width
< desc
->width
)
3743 while (pow2_height
< desc
->height
)
3745 texture
->flags
|= WINED3D_TEXTURE_COND_NP2_EMULATED
;
3748 texture
->pow2_width
= pow2_width
;
3749 texture
->pow2_height
= pow2_height
;
3751 if ((pow2_width
> d3d_info
->limits
.texture_size
|| pow2_height
> d3d_info
->limits
.texture_size
)
3752 && (desc
->bind_flags
& WINED3D_BIND_SHADER_RESOURCE
))
3754 /* One of four options:
3755 * 1: Do the same as we do with NPOT and scale the texture. (Any
3756 * texture ops would require the texture to be scaled which is
3757 * potentially slow.)
3758 * 2: Set the texture to the maximum size (bad idea).
3759 * 3: WARN and return WINED3DERR_NOTAVAILABLE.
3760 * 4: Create the surface, but allow it to be used only for DirectDraw
3761 * Blts. Some apps (e.g. Swat 3) create textures with a height of
3762 * 16 and a width > 3000 and blt 16x16 letter areas from them to
3763 * the render target. */
3764 if (desc
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
3766 WARN("Dimensions (%ux%u) exceed the maximum texture size.\n", pow2_width
, pow2_height
);
3767 return WINED3DERR_NOTAVAILABLE
;
3770 /* We should never use this surface in combination with OpenGL. */
3771 TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width
, pow2_height
);
3774 for (i
= 0; i
< layer_count
; ++i
)
3776 for (j
= 0; j
< level_count
; ++j
)
3778 unsigned int idx
= i
* level_count
+ j
;
3780 size
= wined3d_format_calculate_size(format
, device
->surface_alignment
,
3781 max(1, desc
->width
>> j
), max(1, desc
->height
>> j
), max(1, desc
->depth
>> j
));
3782 texture
->sub_resources
[idx
].offset
= offset
;
3783 texture
->sub_resources
[idx
].size
= size
;
3786 offset
= (offset
+ (RESOURCE_ALIGNMENT
- 1)) & ~(RESOURCE_ALIGNMENT
- 1);
3790 return WINED3DERR_INVALIDCALL
;
3792 /* Ensure the last mip-level is at least large enough to hold a single
3793 * compressed block. It is questionable how useful these mip-levels are to
3794 * the application with "broken pitch" formats, but we want to avoid
3795 * memory corruption when loading textures into WINED3D_LOCATION_SYSMEM. */
3796 if (format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_BROKEN_PITCH
)
3798 unsigned int min_size
;
3800 min_size
= texture
->sub_resources
[level_count
* layer_count
- 1].offset
+ format
->block_byte_count
;
3801 min_size
= (min_size
+ (RESOURCE_ALIGNMENT
- 1)) & ~(RESOURCE_ALIGNMENT
- 1);
3802 if (min_size
> offset
)
3806 if (FAILED(hr
= resource_init(&texture
->resource
, device
, desc
->resource_type
, format
,
3807 desc
->multisample_type
, desc
->multisample_quality
, desc
->usage
, desc
->bind_flags
, desc
->access
,
3808 desc
->width
, desc
->height
, desc
->depth
, offset
, parent
, parent_ops
, &texture_resource_ops
)))
3810 static unsigned int once
;
3812 /* DXTn 3D textures are not supported. Do not write the ERR for them. */
3813 if ((desc
->format
== WINED3DFMT_DXT1
|| desc
->format
== WINED3DFMT_DXT2
|| desc
->format
== WINED3DFMT_DXT3
3814 || desc
->format
== WINED3DFMT_DXT4
|| desc
->format
== WINED3DFMT_DXT5
)
3815 && !(format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_TEXTURE
)
3816 && desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
&& !once
++)
3817 ERR_(winediag
)("The application tried to create a DXTn texture, but the driver does not support them.\n");
3819 WARN("Failed to initialize resource, returning %#x\n", hr
);
3822 wined3d_resource_update_draw_binding(&texture
->resource
);
3824 texture
->texture_ops
= texture_ops
;
3826 texture
->layer_count
= layer_count
;
3827 texture
->level_count
= level_count
;
3829 texture
->flags
|= WINED3D_TEXTURE_POW2_MAT_IDENT
| WINED3D_TEXTURE_NORMALIZED_COORDS
3830 | WINED3D_TEXTURE_DOWNLOADABLE
;
3831 if (flags
& WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
)
3832 texture
->flags
|= WINED3D_TEXTURE_PIN_SYSMEM
| WINED3D_TEXTURE_GET_DC_LENIENT
;
3833 if (flags
& (WINED3D_TEXTURE_CREATE_GET_DC
| WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
))
3834 texture
->flags
|= WINED3D_TEXTURE_GET_DC
;
3835 if (flags
& WINED3D_TEXTURE_CREATE_DISCARD
)
3836 texture
->flags
|= WINED3D_TEXTURE_DISCARD
;
3837 if (flags
& WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS
)
3839 if (!(texture
->resource
.format_flags
& WINED3DFMT_FLAG_GEN_MIPMAP
))
3840 WARN("Format doesn't support mipmaps generation, "
3841 "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n");
3843 texture
->flags
|= WINED3D_TEXTURE_GENERATE_MIPMAPS
;
3846 if (flags
& WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS
3847 && !(texture
->dirty_regions
= heap_calloc(texture
->layer_count
, sizeof(*texture
->dirty_regions
))))
3849 wined3d_texture_cleanup_sync(texture
);
3850 return E_OUTOFMEMORY
;
3853 /* Precalculated scaling for 'faked' non power of two texture coords. */
3854 if (texture
->resource
.gl_type
== WINED3D_GL_RES_TYPE_TEX_RECT
)
3856 texture
->pow2_matrix
[0] = (float)desc
->width
;
3857 texture
->pow2_matrix
[5] = (float)desc
->height
;
3858 texture
->flags
&= ~(WINED3D_TEXTURE_POW2_MAT_IDENT
| WINED3D_TEXTURE_NORMALIZED_COORDS
);
3860 else if (texture
->flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
3862 texture
->pow2_matrix
[0] = (((float)desc
->width
) / ((float)pow2_width
));
3863 texture
->pow2_matrix
[5] = (((float)desc
->height
) / ((float)pow2_height
));
3864 texture
->flags
&= ~WINED3D_TEXTURE_POW2_MAT_IDENT
;
3868 texture
->pow2_matrix
[0] = 1.0f
;
3869 texture
->pow2_matrix
[5] = 1.0f
;
3871 texture
->pow2_matrix
[10] = 1.0f
;
3872 texture
->pow2_matrix
[15] = 1.0f
;
3873 TRACE("x scale %.8e, y scale %.8e.\n", texture
->pow2_matrix
[0], texture
->pow2_matrix
[5]);
3875 if (wined3d_texture_use_pbo(texture
, gl_info
))
3876 texture
->resource
.map_binding
= WINED3D_LOCATION_BUFFER
;
3878 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
3879 || !wined3d_texture_use_pbo(texture
, gl_info
))
3881 if (!wined3d_resource_prepare_sysmem(&texture
->resource
))
3883 wined3d_texture_cleanup_sync(texture
);
3884 return E_OUTOFMEMORY
;
3888 sub_count
= level_count
* layer_count
;
3889 if (sub_count
/ layer_count
!= level_count
)
3891 wined3d_texture_cleanup_sync(texture
);
3892 return E_OUTOFMEMORY
;
3895 if (desc
->usage
& WINED3DUSAGE_OVERLAY
)
3897 if (!(texture
->overlay_info
= heap_calloc(sub_count
, sizeof(*texture
->overlay_info
))))
3899 wined3d_texture_cleanup_sync(texture
);
3900 return E_OUTOFMEMORY
;
3903 for (i
= 0; i
< sub_count
; ++i
)
3905 list_init(&texture
->overlay_info
[i
].entry
);
3906 list_init(&texture
->overlay_info
[i
].overlays
);
3910 /* Generate all sub-resources. */
3911 for (i
= 0; i
< sub_count
; ++i
)
3913 struct wined3d_texture_sub_resource
*sub_resource
;
3915 sub_resource
= &texture
->sub_resources
[i
];
3916 sub_resource
->locations
= WINED3D_LOCATION_DISCARDED
;
3917 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
)
3919 wined3d_texture_validate_location(texture
, i
, WINED3D_LOCATION_SYSMEM
);
3920 wined3d_texture_invalidate_location(texture
, i
, ~WINED3D_LOCATION_SYSMEM
);
3923 if (FAILED(hr
= device_parent
->ops
->texture_sub_resource_created(device_parent
,
3924 desc
->resource_type
, texture
, i
, &sub_resource
->parent
, &sub_resource
->parent_ops
)))
3926 WARN("Failed to create sub-resource parent, hr %#x.\n", hr
);
3927 sub_resource
->parent
= NULL
;
3928 wined3d_texture_cleanup_sync(texture
);
3932 TRACE("parent %p, parent_ops %p.\n", sub_resource
->parent
, sub_resource
->parent_ops
);
3934 TRACE("Created sub-resource %u (level %u, layer %u).\n",
3935 i
, i
% texture
->level_count
, i
/ texture
->level_count
);
3937 if (desc
->usage
& WINED3DUSAGE_OWNDC
)
3939 struct wined3d_texture_idx texture_idx
= {texture
, i
};
3941 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
3942 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
3943 if (!texture
->dc_info
|| !texture
->dc_info
[i
].dc
)
3945 wined3d_texture_cleanup_sync(texture
);
3946 return WINED3DERR_INVALIDCALL
;
3954 HRESULT CDECL
wined3d_device_context_blt(struct wined3d_device_context
*context
,
3955 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, const RECT
*dst_rect
,
3956 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, const RECT
*src_rect
,
3957 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
3959 struct wined3d_box src_box
= {src_rect
->left
, src_rect
->top
, src_rect
->right
, src_rect
->bottom
, 0, 1};
3960 struct wined3d_box dst_box
= {dst_rect
->left
, dst_rect
->top
, dst_rect
->right
, dst_rect
->bottom
, 0, 1};
3963 TRACE("context %p, dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, "
3964 "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n",
3965 context
, dst_texture
, dst_sub_resource_idx
, wine_dbgstr_rect(dst_rect
), src_texture
,
3966 src_sub_resource_idx
, wine_dbgstr_rect(src_rect
), flags
, fx
, debug_d3dtexturefiltertype(filter
));
3968 if (dst_sub_resource_idx
>= dst_texture
->level_count
* dst_texture
->layer_count
3969 || dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
3970 return WINED3DERR_INVALIDCALL
;
3972 if (src_sub_resource_idx
>= src_texture
->level_count
* src_texture
->layer_count
3973 || src_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
3974 return WINED3DERR_INVALIDCALL
;
3976 if (filter
!= WINED3D_TEXF_NONE
&& filter
!= WINED3D_TEXF_POINT
3977 && filter
!= WINED3D_TEXF_LINEAR
)
3978 return WINED3DERR_INVALIDCALL
;
3980 if (FAILED(hr
= wined3d_resource_check_box_dimensions(&dst_texture
->resource
, dst_sub_resource_idx
, &dst_box
)))
3983 if (FAILED(hr
= wined3d_resource_check_box_dimensions(&src_texture
->resource
, src_sub_resource_idx
, &src_box
)))
3986 if (dst_texture
->sub_resources
[dst_sub_resource_idx
].map_count
3987 || src_texture
->sub_resources
[src_sub_resource_idx
].map_count
)
3989 WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n");
3990 return WINEDDERR_SURFACEBUSY
;
3993 if (!src_texture
->resource
.format
->depth_size
!= !dst_texture
->resource
.format
->depth_size
3994 || !src_texture
->resource
.format
->stencil_size
!= !dst_texture
->resource
.format
->stencil_size
)
3996 WARN("Rejecting depth/stencil blit between incompatible formats.\n");
3997 return WINED3DERR_INVALIDCALL
;
4000 if (dst_texture
->resource
.device
!= src_texture
->resource
.device
)
4002 FIXME("Rejecting cross-device blit.\n");
4006 wined3d_device_context_emit_blt_sub_resource(&dst_texture
->resource
.device
->cs
->c
, &dst_texture
->resource
,
4007 dst_sub_resource_idx
, &dst_box
, &src_texture
->resource
, src_sub_resource_idx
, &src_box
, flags
, fx
, filter
);
4012 HRESULT CDECL
wined3d_texture_get_overlay_position(const struct wined3d_texture
*texture
,
4013 unsigned int sub_resource_idx
, LONG
*x
, LONG
*y
)
4015 struct wined3d_overlay_info
*overlay
;
4017 TRACE("texture %p, sub_resource_idx %u, x %p, y %p.\n", texture
, sub_resource_idx
, x
, y
);
4019 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
)
4020 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4022 WARN("Invalid sub-resource specified.\n");
4023 return WINEDDERR_NOTAOVERLAYSURFACE
;
4026 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4027 if (!overlay
->dst_texture
)
4029 TRACE("Overlay not visible.\n");
4032 return WINEDDERR_OVERLAYNOTVISIBLE
;
4035 *x
= overlay
->dst_rect
.left
;
4036 *y
= overlay
->dst_rect
.top
;
4038 TRACE("Returning position %d, %d.\n", *x
, *y
);
4043 HRESULT CDECL
wined3d_texture_set_overlay_position(struct wined3d_texture
*texture
,
4044 unsigned int sub_resource_idx
, LONG x
, LONG y
)
4046 struct wined3d_overlay_info
*overlay
;
4049 TRACE("texture %p, sub_resource_idx %u, x %d, y %d.\n", texture
, sub_resource_idx
, x
, y
);
4051 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
)
4052 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4054 WARN("Invalid sub-resource specified.\n");
4055 return WINEDDERR_NOTAOVERLAYSURFACE
;
4058 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4059 w
= overlay
->dst_rect
.right
- overlay
->dst_rect
.left
;
4060 h
= overlay
->dst_rect
.bottom
- overlay
->dst_rect
.top
;
4061 SetRect(&overlay
->dst_rect
, x
, y
, x
+ w
, y
+ h
);
4066 HRESULT CDECL
wined3d_texture_update_overlay(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
4067 const RECT
*src_rect
, struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4068 const RECT
*dst_rect
, DWORD flags
)
4070 struct wined3d_overlay_info
*overlay
;
4071 unsigned int level
, dst_level
;
4073 TRACE("texture %p, sub_resource_idx %u, src_rect %s, dst_texture %p, "
4074 "dst_sub_resource_idx %u, dst_rect %s, flags %#x.\n",
4075 texture
, sub_resource_idx
, wine_dbgstr_rect(src_rect
), dst_texture
,
4076 dst_sub_resource_idx
, wine_dbgstr_rect(dst_rect
), flags
);
4078 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
) || texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
4079 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4081 WARN("Invalid sub-resource specified.\n");
4082 return WINEDDERR_NOTAOVERLAYSURFACE
;
4085 if (!dst_texture
|| dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
4086 || dst_sub_resource_idx
>= dst_texture
->level_count
* dst_texture
->layer_count
)
4088 WARN("Invalid destination sub-resource specified.\n");
4089 return WINED3DERR_INVALIDCALL
;
4092 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4094 level
= sub_resource_idx
% texture
->level_count
;
4096 overlay
->src_rect
= *src_rect
;
4098 SetRect(&overlay
->src_rect
, 0, 0,
4099 wined3d_texture_get_level_width(texture
, level
),
4100 wined3d_texture_get_level_height(texture
, level
));
4102 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4104 overlay
->dst_rect
= *dst_rect
;
4106 SetRect(&overlay
->dst_rect
, 0, 0,
4107 wined3d_texture_get_level_width(dst_texture
, dst_level
),
4108 wined3d_texture_get_level_height(dst_texture
, dst_level
));
4110 if (overlay
->dst_texture
&& (overlay
->dst_texture
!= dst_texture
4111 || overlay
->dst_sub_resource_idx
!= dst_sub_resource_idx
|| flags
& WINEDDOVER_HIDE
))
4113 overlay
->dst_texture
= NULL
;
4114 list_remove(&overlay
->entry
);
4117 if (flags
& WINEDDOVER_SHOW
)
4119 if (overlay
->dst_texture
!= dst_texture
|| overlay
->dst_sub_resource_idx
!= dst_sub_resource_idx
)
4121 overlay
->dst_texture
= dst_texture
;
4122 overlay
->dst_sub_resource_idx
= dst_sub_resource_idx
;
4123 list_add_tail(&texture
->overlay_info
[dst_sub_resource_idx
].overlays
, &overlay
->entry
);
4126 else if (flags
& WINEDDOVER_HIDE
)
4128 /* Tests show that the rectangles are erased on hide. */
4129 SetRectEmpty(&overlay
->src_rect
);
4130 SetRectEmpty(&overlay
->dst_rect
);
4131 overlay
->dst_texture
= NULL
;
4137 void * CDECL
wined3d_texture_get_sub_resource_parent(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
)
4139 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4141 TRACE("texture %p, sub_resource_idx %u.\n", texture
, sub_resource_idx
);
4143 if (sub_resource_idx
>= sub_count
)
4145 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4149 return texture
->sub_resources
[sub_resource_idx
].parent
;
4152 void CDECL
wined3d_texture_set_sub_resource_parent(struct wined3d_texture
*texture
,
4153 unsigned int sub_resource_idx
, void *parent
)
4155 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4157 TRACE("texture %p, sub_resource_idx %u, parent %p.\n", texture
, sub_resource_idx
, parent
);
4159 if (sub_resource_idx
>= sub_count
)
4161 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4165 texture
->sub_resources
[sub_resource_idx
].parent
= parent
;
4168 HRESULT CDECL
wined3d_texture_get_sub_resource_desc(const struct wined3d_texture
*texture
,
4169 unsigned int sub_resource_idx
, struct wined3d_sub_resource_desc
*desc
)
4171 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4172 const struct wined3d_resource
*resource
;
4173 unsigned int level_idx
;
4175 TRACE("texture %p, sub_resource_idx %u, desc %p.\n", texture
, sub_resource_idx
, desc
);
4177 if (sub_resource_idx
>= sub_count
)
4179 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4180 return WINED3DERR_INVALIDCALL
;
4183 resource
= &texture
->resource
;
4184 desc
->format
= resource
->format
->id
;
4185 desc
->multisample_type
= resource
->multisample_type
;
4186 desc
->multisample_quality
= resource
->multisample_quality
;
4187 desc
->usage
= resource
->usage
;
4188 desc
->bind_flags
= resource
->bind_flags
;
4189 desc
->access
= resource
->access
;
4191 level_idx
= sub_resource_idx
% texture
->level_count
;
4192 desc
->width
= wined3d_texture_get_level_width(texture
, level_idx
);
4193 desc
->height
= wined3d_texture_get_level_height(texture
, level_idx
);
4194 desc
->depth
= wined3d_texture_get_level_depth(texture
, level_idx
);
4195 desc
->size
= texture
->sub_resources
[sub_resource_idx
].size
;
4200 HRESULT
wined3d_texture_gl_init(struct wined3d_texture_gl
*texture_gl
, struct wined3d_device
*device
,
4201 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
4202 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
4204 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
4207 TRACE("texture_gl %p, device %p, desc %p, layer_count %u, "
4208 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
4209 texture_gl
, device
, desc
, layer_count
,
4210 level_count
, flags
, parent
, parent_ops
);
4212 if (!(desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
) && layer_count
> 1
4213 && !gl_info
->supported
[EXT_TEXTURE_ARRAY
])
4215 WARN("OpenGL implementation does not support array textures.\n");
4216 return WINED3DERR_INVALIDCALL
;
4219 switch (desc
->resource_type
)
4221 case WINED3D_RTYPE_TEXTURE_1D
:
4222 if (layer_count
> 1)
4223 texture_gl
->target
= GL_TEXTURE_1D_ARRAY
;
4225 texture_gl
->target
= GL_TEXTURE_1D
;
4228 case WINED3D_RTYPE_TEXTURE_2D
:
4229 if (desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
)
4231 texture_gl
->target
= GL_TEXTURE_CUBE_MAP_ARB
;
4233 else if (desc
->multisample_type
&& gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
4235 if (layer_count
> 1)
4236 texture_gl
->target
= GL_TEXTURE_2D_MULTISAMPLE_ARRAY
;
4238 texture_gl
->target
= GL_TEXTURE_2D_MULTISAMPLE
;
4242 if (layer_count
> 1)
4243 texture_gl
->target
= GL_TEXTURE_2D_ARRAY
;
4245 texture_gl
->target
= GL_TEXTURE_2D
;
4249 case WINED3D_RTYPE_TEXTURE_3D
:
4250 if (!gl_info
->supported
[EXT_TEXTURE3D
])
4252 WARN("OpenGL implementation does not support 3D textures.\n");
4253 return WINED3DERR_INVALIDCALL
;
4255 texture_gl
->target
= GL_TEXTURE_3D
;
4259 ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc
->resource_type
));
4260 return WINED3DERR_INVALIDCALL
;
4263 list_init(&texture_gl
->renderbuffers
);
4265 if (FAILED(hr
= wined3d_texture_init(&texture_gl
->t
, desc
, layer_count
, level_count
,
4266 flags
, device
, parent
, parent_ops
, &texture_gl
[1], &texture_gl_ops
)))
4269 if (texture_gl
->t
.resource
.gl_type
== WINED3D_GL_RES_TYPE_TEX_RECT
)
4270 texture_gl
->target
= GL_TEXTURE_RECTANGLE_ARB
;
4272 if (texture_gl
->target
== GL_TEXTURE_2D_MULTISAMPLE_ARRAY
|| texture_gl
->target
== GL_TEXTURE_2D_MULTISAMPLE
)
4273 texture_gl
->t
.flags
&= ~WINED3D_TEXTURE_DOWNLOADABLE
;
4278 HRESULT CDECL
wined3d_texture_create(struct wined3d_device
*device
, const struct wined3d_resource_desc
*desc
,
4279 UINT layer_count
, UINT level_count
, DWORD flags
, const struct wined3d_sub_resource_data
*data
,
4280 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
4282 unsigned int sub_count
= level_count
* layer_count
;
4286 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, data %p, "
4287 "parent %p, parent_ops %p, texture %p.\n",
4288 device
, desc
, layer_count
, level_count
, flags
, data
, parent
, parent_ops
, texture
);
4292 WARN("Invalid layer count.\n");
4293 return E_INVALIDARG
;
4295 if ((desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
) && layer_count
!= 6)
4297 ERR("Invalid layer count %u for legacy cubemap.\n", layer_count
);
4303 WARN("Invalid level count.\n");
4304 return WINED3DERR_INVALIDCALL
;
4307 if (desc
->multisample_type
!= WINED3D_MULTISAMPLE_NONE
)
4309 const struct wined3d_format
*format
= wined3d_get_format(device
->adapter
, desc
->format
, desc
->bind_flags
);
4311 if (desc
->multisample_type
== WINED3D_MULTISAMPLE_NON_MASKABLE
4312 && desc
->multisample_quality
>= wined3d_popcount(format
->multisample_types
))
4314 WARN("Unsupported quality level %u requested for WINED3D_MULTISAMPLE_NON_MASKABLE.\n",
4315 desc
->multisample_quality
);
4316 return WINED3DERR_NOTAVAILABLE
;
4318 if (desc
->multisample_type
!= WINED3D_MULTISAMPLE_NON_MASKABLE
4319 && (!(format
->multisample_types
& 1u << (desc
->multisample_type
- 1))
4320 || (desc
->multisample_quality
&& desc
->multisample_quality
!= WINED3D_STANDARD_MULTISAMPLE_PATTERN
)))
4322 WARN("Unsupported multisample type %u quality %u requested.\n", desc
->multisample_type
,
4323 desc
->multisample_quality
);
4324 return WINED3DERR_NOTAVAILABLE
;
4330 for (i
= 0; i
< sub_count
; ++i
)
4335 WARN("Invalid sub-resource data specified for sub-resource %u.\n", i
);
4336 return E_INVALIDARG
;
4340 if (FAILED(hr
= device
->adapter
->adapter_ops
->adapter_create_texture(device
, desc
,
4341 layer_count
, level_count
, flags
, parent
, parent_ops
, texture
)))
4344 /* FIXME: We'd like to avoid ever allocating system memory for the texture
4348 struct wined3d_box box
;
4350 for (i
= 0; i
< sub_count
; ++i
)
4352 wined3d_texture_get_level_box(*texture
, i
% (*texture
)->level_count
, &box
);
4353 wined3d_device_context_emit_update_sub_resource(&device
->cs
->c
, &(*texture
)->resource
,
4354 i
, &box
, data
[i
].data
, data
[i
].row_pitch
, data
[i
].slice_pitch
);
4358 TRACE("Created texture %p.\n", *texture
);
4363 HRESULT CDECL
wined3d_texture_get_dc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
, HDC
*dc
)
4365 struct wined3d_device
*device
= texture
->resource
.device
;
4366 struct wined3d_texture_sub_resource
*sub_resource
;
4367 struct wined3d_dc_info
*dc_info
;
4369 TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture
, sub_resource_idx
, dc
);
4371 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC
))
4373 WARN("Texture does not support GetDC\n");
4374 /* Don't touch the DC */
4375 return WINED3DERR_INVALIDCALL
;
4378 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
4379 return WINED3DERR_INVALIDCALL
;
4381 if (texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4383 WARN("Not supported on %s resources.\n", debug_d3dresourcetype(texture
->resource
.type
));
4384 return WINED3DERR_INVALIDCALL
;
4387 if (texture
->resource
.map_count
&& !(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4388 return WINED3DERR_INVALIDCALL
;
4390 if (!(dc_info
= texture
->dc_info
) || !dc_info
[sub_resource_idx
].dc
)
4392 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
4394 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
4395 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
4396 if (!(dc_info
= texture
->dc_info
) || !dc_info
[sub_resource_idx
].dc
)
4397 return WINED3DERR_INVALIDCALL
;
4400 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4401 texture
->flags
|= WINED3D_TEXTURE_DC_IN_USE
;
4402 ++texture
->resource
.map_count
;
4403 ++sub_resource
->map_count
;
4405 *dc
= dc_info
[sub_resource_idx
].dc
;
4406 TRACE("Returning dc %p.\n", *dc
);
4411 HRESULT CDECL
wined3d_texture_release_dc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
, HDC dc
)
4413 struct wined3d_device
*device
= texture
->resource
.device
;
4414 struct wined3d_texture_sub_resource
*sub_resource
;
4415 struct wined3d_dc_info
*dc_info
;
4417 TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture
, sub_resource_idx
, dc
);
4419 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
4420 return WINED3DERR_INVALIDCALL
;
4422 if (texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4424 WARN("Not supported on %s resources.\n", debug_d3dresourcetype(texture
->resource
.type
));
4425 return WINED3DERR_INVALIDCALL
;
4428 if (!(texture
->flags
& (WINED3D_TEXTURE_GET_DC_LENIENT
| WINED3D_TEXTURE_DC_IN_USE
)))
4429 return WINED3DERR_INVALIDCALL
;
4431 if (!(dc_info
= texture
->dc_info
) || dc_info
[sub_resource_idx
].dc
!= dc
)
4433 WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n",
4434 dc
, dc_info
? dc_info
[sub_resource_idx
].dc
: NULL
);
4435 return WINED3DERR_INVALIDCALL
;
4438 if (!(texture
->resource
.usage
& WINED3DUSAGE_OWNDC
))
4440 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
4442 wined3d_cs_destroy_object(device
->cs
, wined3d_texture_destroy_dc
, &texture_idx
);
4443 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
4446 --sub_resource
->map_count
;
4447 if (!--texture
->resource
.map_count
&& texture
->update_map_binding
)
4448 wined3d_texture_update_map_binding(texture
);
4449 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4450 texture
->flags
&= ~WINED3D_TEXTURE_DC_IN_USE
;
4455 void wined3d_texture_upload_from_texture(struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4456 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
, struct wined3d_texture
*src_texture
,
4457 unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
)
4459 unsigned int src_row_pitch
, src_slice_pitch
;
4460 unsigned int update_w
, update_h
, update_d
;
4461 unsigned int src_level
, dst_level
;
4462 struct wined3d_context
*context
;
4463 struct wined3d_bo_address data
;
4465 TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
4466 "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
4467 dst_texture
, dst_sub_resource_idx
, dst_x
, dst_y
, dst_z
,
4468 src_texture
, src_sub_resource_idx
, debug_box(src_box
));
4470 context
= context_acquire(dst_texture
->resource
.device
, NULL
, 0);
4472 /* Only load the sub-resource for partial updates. For newly allocated
4473 * textures the texture wouldn't be the current location, and we'd upload
4474 * zeroes just to overwrite them again. */
4475 update_w
= src_box
->right
- src_box
->left
;
4476 update_h
= src_box
->bottom
- src_box
->top
;
4477 update_d
= src_box
->back
- src_box
->front
;
4478 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4479 if (update_w
== wined3d_texture_get_level_width(dst_texture
, dst_level
)
4480 && update_h
== wined3d_texture_get_level_height(dst_texture
, dst_level
)
4481 && update_d
== wined3d_texture_get_level_depth(dst_texture
, dst_level
))
4482 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
4484 wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
4486 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4487 wined3d_texture_get_memory(src_texture
, src_sub_resource_idx
, &data
,
4488 src_texture
->sub_resources
[src_sub_resource_idx
].locations
);
4489 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
4491 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&data
),
4492 src_texture
->resource
.format
, src_box
, src_row_pitch
, src_slice_pitch
, dst_texture
,
4493 dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, dst_x
, dst_y
, dst_z
);
4495 context_release(context
);
4497 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
4498 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
4501 /* Partial downloads are not supported. */
4502 void wined3d_texture_download_from_texture(struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4503 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
)
4505 unsigned int src_level
, dst_level
, dst_row_pitch
, dst_slice_pitch
;
4506 unsigned int dst_location
= dst_texture
->resource
.map_binding
;
4507 struct wined3d_context
*context
;
4508 struct wined3d_bo_address data
;
4509 struct wined3d_box src_box
;
4510 unsigned int src_location
;
4512 context
= context_acquire(src_texture
->resource
.device
, NULL
, 0);
4514 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
4515 wined3d_texture_get_memory(dst_texture
, dst_sub_resource_idx
, &data
, dst_location
);
4517 if (src_texture
->sub_resources
[src_sub_resource_idx
].locations
& WINED3D_LOCATION_TEXTURE_RGB
)
4518 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
4520 src_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
4521 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4522 wined3d_texture_get_level_box(src_texture
, src_level
, &src_box
);
4524 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4525 wined3d_texture_get_pitch(dst_texture
, dst_level
, &dst_row_pitch
, &dst_slice_pitch
);
4527 src_texture
->texture_ops
->texture_download_data(context
, src_texture
, src_sub_resource_idx
, src_location
,
4528 &src_box
, &data
, dst_texture
->resource
.format
, 0, 0, 0, dst_row_pitch
, dst_slice_pitch
);
4530 context_release(context
);
4532 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, dst_location
);
4533 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~dst_location
);
4536 static void wined3d_texture_no3d_upload_data(struct wined3d_context
*context
,
4537 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
4538 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
4539 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
4540 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
4542 FIXME("Not implemented.\n");
4545 static void wined3d_texture_no3d_download_data(struct wined3d_context
*context
,
4546 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
4547 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
4548 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
4549 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
4551 FIXME("Not implemented.\n");
4554 static BOOL
wined3d_texture_no3d_prepare_location(struct wined3d_texture
*texture
,
4555 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
4557 if (location
== WINED3D_LOCATION_SYSMEM
)
4558 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
4559 : wined3d_resource_prepare_sysmem(&texture
->resource
);
4561 FIXME("Unhandled location %s.\n", wined3d_debug_location(location
));
4565 static BOOL
wined3d_texture_no3d_load_location(struct wined3d_texture
*texture
,
4566 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
4568 TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
4569 texture
, sub_resource_idx
, context
, wined3d_debug_location(location
));
4571 if (location
== WINED3D_LOCATION_SYSMEM
)
4574 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
4579 static void wined3d_texture_no3d_unload_location(struct wined3d_texture
*texture
,
4580 struct wined3d_context
*context
, unsigned int location
)
4582 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
4585 static const struct wined3d_texture_ops wined3d_texture_no3d_ops
=
4587 wined3d_texture_no3d_prepare_location
,
4588 wined3d_texture_no3d_load_location
,
4589 wined3d_texture_no3d_unload_location
,
4590 wined3d_texture_no3d_upload_data
,
4591 wined3d_texture_no3d_download_data
,
4594 HRESULT
wined3d_texture_no3d_init(struct wined3d_texture
*texture_no3d
, struct wined3d_device
*device
,
4595 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
4596 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
4598 TRACE("texture_no3d %p, device %p, desc %p, layer_count %u, "
4599 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
4600 texture_no3d
, device
, desc
, layer_count
,
4601 level_count
, flags
, parent
, parent_ops
);
4603 return wined3d_texture_init(texture_no3d
, desc
, layer_count
, level_count
,
4604 flags
, device
, parent
, parent_ops
, &texture_no3d
[1], &wined3d_texture_no3d_ops
);
4607 void wined3d_vk_swizzle_from_color_fixup(VkComponentMapping
*mapping
, struct color_fixup_desc fixup
)
4609 static const VkComponentSwizzle swizzle_source
[] =
4611 VK_COMPONENT_SWIZZLE_ZERO
, /* CHANNEL_SOURCE_ZERO */
4612 VK_COMPONENT_SWIZZLE_ONE
, /* CHANNEL_SOURCE_ONE */
4613 VK_COMPONENT_SWIZZLE_R
, /* CHANNEL_SOURCE_X */
4614 VK_COMPONENT_SWIZZLE_G
, /* CHANNEL_SOURCE_Y */
4615 VK_COMPONENT_SWIZZLE_B
, /* CHANNEL_SOURCE_Z */
4616 VK_COMPONENT_SWIZZLE_A
, /* CHANNEL_SOURCE_W */
4619 mapping
->r
= swizzle_source
[fixup
.x_source
];
4620 mapping
->g
= swizzle_source
[fixup
.y_source
];
4621 mapping
->b
= swizzle_source
[fixup
.z_source
];
4622 mapping
->a
= swizzle_source
[fixup
.w_source
];
4625 const VkDescriptorImageInfo
*wined3d_texture_vk_get_default_image_info(struct wined3d_texture_vk
*texture_vk
,
4626 struct wined3d_context_vk
*context_vk
)
4628 const struct wined3d_format_vk
*format_vk
;
4629 const struct wined3d_vk_info
*vk_info
;
4630 struct wined3d_device_vk
*device_vk
;
4631 VkImageViewCreateInfo create_info
;
4632 struct color_fixup_desc fixup
;
4636 if (texture_vk
->default_image_info
.imageView
)
4637 return &texture_vk
->default_image_info
;
4639 format_vk
= wined3d_format_vk(texture_vk
->t
.resource
.format
);
4640 device_vk
= wined3d_device_vk(texture_vk
->t
.resource
.device
);
4641 vk_info
= context_vk
->vk_info
;
4643 if (texture_vk
->t
.layer_count
> 1)
4644 flags
|= WINED3D_VIEW_TEXTURE_ARRAY
;
4646 wined3d_texture_vk_prepare_texture(texture_vk
, context_vk
);
4647 create_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
;
4648 create_info
.pNext
= NULL
;
4649 create_info
.flags
= 0;
4650 create_info
.image
= texture_vk
->image
.vk_image
;
4651 create_info
.viewType
= vk_image_view_type_from_wined3d(texture_vk
->t
.resource
.type
, flags
);
4652 create_info
.format
= format_vk
->vk_format
;
4653 fixup
= format_vk
->f
.color_fixup
;
4654 if (is_identity_fixup(fixup
) || !can_use_texture_swizzle(context_vk
->c
.d3d_info
, &format_vk
->f
))
4656 create_info
.components
.r
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4657 create_info
.components
.g
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4658 create_info
.components
.b
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4659 create_info
.components
.a
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4663 wined3d_vk_swizzle_from_color_fixup(&create_info
.components
, fixup
);
4665 create_info
.subresourceRange
.aspectMask
= vk_aspect_mask_from_format(&format_vk
->f
);
4666 create_info
.subresourceRange
.baseMipLevel
= 0;
4667 create_info
.subresourceRange
.levelCount
= texture_vk
->t
.level_count
;
4668 create_info
.subresourceRange
.baseArrayLayer
= 0;
4669 create_info
.subresourceRange
.layerCount
= texture_vk
->t
.layer_count
;
4670 if ((vr
= VK_CALL(vkCreateImageView(device_vk
->vk_device
, &create_info
,
4671 NULL
, &texture_vk
->default_image_info
.imageView
))) < 0)
4673 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr
));
4677 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(texture_vk
->default_image_info
.imageView
));
4679 texture_vk
->default_image_info
.sampler
= VK_NULL_HANDLE
;
4680 texture_vk
->default_image_info
.imageLayout
= texture_vk
->layout
;
4682 return &texture_vk
->default_image_info
;
4685 static void wined3d_texture_vk_upload_data(struct wined3d_context
*context
,
4686 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
4687 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
4688 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
4689 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
4691 struct wined3d_texture_vk
*dst_texture_vk
= wined3d_texture_vk(dst_texture
);
4692 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
4693 unsigned int dst_level
, dst_row_pitch
, dst_slice_pitch
;
4694 struct wined3d_texture_sub_resource
*sub_resource
;
4695 struct wined3d_bo_address staging_bo_addr
;
4696 const struct wined3d_vk_info
*vk_info
;
4697 VkCommandBuffer vk_command_buffer
;
4698 VkImageSubresourceRange vk_range
;
4699 struct wined3d_bo_vk staging_bo
;
4700 VkImageAspectFlags aspect_mask
;
4701 struct wined3d_range range
;
4702 VkBufferImageCopy region
;
4706 TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, "
4707 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n",
4708 context
, debug_const_bo_address(src_bo_addr
), debug_d3dformat(src_format
->id
), debug_box(src_box
),
4709 src_row_pitch
, src_slice_pitch
, dst_texture
, dst_sub_resource_idx
,
4710 wined3d_debug_location(dst_location
), dst_x
, dst_y
, dst_z
);
4712 if (src_bo_addr
->buffer_object
)
4714 FIXME("Unhandled buffer object %#lx.\n", src_bo_addr
->buffer_object
);
4718 if (src_format
->id
!= dst_texture
->resource
.format
->id
)
4720 FIXME("Unhandled format conversion (%s -> %s).\n",
4721 debug_d3dformat(src_format
->id
),
4722 debug_d3dformat(dst_texture
->resource
.format
->id
));
4726 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4727 wined3d_texture_get_pitch(dst_texture
, dst_level
, &dst_row_pitch
, &dst_slice_pitch
);
4728 if (dst_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_1D
)
4729 src_row_pitch
= dst_row_pitch
= 0;
4730 if (dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_3D
)
4731 src_slice_pitch
= dst_slice_pitch
= 0;
4733 if (dst_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
4735 FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location
));
4739 if (wined3d_resource_get_sample_count(&dst_texture_vk
->t
.resource
) > 1)
4741 FIXME("Not supported for multisample textures.\n");
4745 aspect_mask
= vk_aspect_mask_from_format(dst_texture
->resource
.format
);
4746 if (wined3d_popcount(aspect_mask
) > 1)
4748 FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(dst_texture
->resource
.format
->id
));
4752 sub_resource
= &dst_texture_vk
->t
.sub_resources
[dst_sub_resource_idx
];
4753 vk_info
= context_vk
->vk_info
;
4755 src_offset
= src_box
->front
* src_slice_pitch
4756 + (src_box
->top
/ src_format
->block_height
) * src_row_pitch
4757 + (src_box
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
4759 if (!wined3d_context_vk_create_bo(context_vk
, sub_resource
->size
,
4760 VK_BUFFER_USAGE_TRANSFER_SRC_BIT
, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
))
4762 ERR("Failed to create staging bo.\n");
4766 staging_bo_addr
.buffer_object
= (uintptr_t)&staging_bo
;
4767 staging_bo_addr
.addr
= NULL
;
4768 if (!(map_ptr
= wined3d_context_map_bo_address(context
, &staging_bo_addr
,
4769 sub_resource
->size
, WINED3D_MAP_DISCARD
| WINED3D_MAP_WRITE
)))
4771 ERR("Failed to map staging bo.\n");
4772 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4776 wined3d_format_copy_data(src_format
, src_bo_addr
->addr
+ src_offset
, src_row_pitch
,
4777 src_slice_pitch
, map_ptr
, dst_row_pitch
, dst_slice_pitch
, src_box
->right
- src_box
->left
,
4778 src_box
->bottom
- src_box
->top
, src_box
->back
- src_box
->front
);
4781 range
.size
= sub_resource
->size
;
4782 wined3d_context_unmap_bo_address(context
, &staging_bo_addr
, 1, &range
);
4784 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
4786 ERR("Failed to get command buffer.\n");
4787 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4791 vk_range
.aspectMask
= aspect_mask
;
4792 vk_range
.baseMipLevel
= dst_level
;
4793 vk_range
.levelCount
= 1;
4794 vk_range
.baseArrayLayer
= dst_sub_resource_idx
/ dst_texture_vk
->t
.level_count
;
4795 vk_range
.layerCount
= 1;
4797 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4798 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
4799 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
4800 VK_ACCESS_TRANSFER_WRITE_BIT
,
4801 dst_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
4802 dst_texture_vk
->image
.vk_image
, &vk_range
);
4804 region
.bufferOffset
= staging_bo
.buffer_offset
;
4805 region
.bufferRowLength
= (dst_row_pitch
/ src_format
->block_byte_count
) * src_format
->block_width
;
4807 region
.bufferImageHeight
= (dst_slice_pitch
/ dst_row_pitch
) * src_format
->block_height
;
4809 region
.bufferImageHeight
= 1;
4810 region
.imageSubresource
.aspectMask
= vk_range
.aspectMask
;
4811 region
.imageSubresource
.mipLevel
= vk_range
.baseMipLevel
;
4812 region
.imageSubresource
.baseArrayLayer
= vk_range
.baseArrayLayer
;
4813 region
.imageSubresource
.layerCount
= vk_range
.layerCount
;
4814 region
.imageOffset
.x
= dst_x
;
4815 region
.imageOffset
.y
= dst_y
;
4816 region
.imageOffset
.z
= dst_z
;
4817 region
.imageExtent
.width
= src_box
->right
- src_box
->left
;
4818 region
.imageExtent
.height
= src_box
->bottom
- src_box
->top
;
4819 region
.imageExtent
.depth
= src_box
->back
- src_box
->front
;
4821 VK_CALL(vkCmdCopyBufferToImage(vk_command_buffer
, staging_bo
.vk_buffer
,
4822 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ®ion
));
4824 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4825 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
4826 VK_ACCESS_TRANSFER_WRITE_BIT
,
4827 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
4828 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
4829 dst_texture_vk
->image
.vk_image
, &vk_range
);
4830 wined3d_context_vk_reference_texture(context_vk
, dst_texture_vk
);
4831 wined3d_context_vk_reference_bo(context_vk
, &staging_bo
);
4832 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4835 static void wined3d_texture_vk_download_data(struct wined3d_context
*context
,
4836 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
4837 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
4838 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
4839 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
4841 struct wined3d_texture_vk
*src_texture_vk
= wined3d_texture_vk(src_texture
);
4842 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
4843 unsigned int src_level
, src_width
, src_height
, src_depth
;
4844 struct wined3d_texture_sub_resource
*sub_resource
;
4845 unsigned int src_row_pitch
, src_slice_pitch
;
4846 struct wined3d_bo_address staging_bo_addr
;
4847 const struct wined3d_vk_info
*vk_info
;
4848 VkCommandBuffer vk_command_buffer
;
4849 VkImageSubresourceRange vk_range
;
4850 struct wined3d_bo_vk staging_bo
;
4851 VkImageAspectFlags aspect_mask
;
4852 VkBufferImageCopy region
;
4855 TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, "
4856 "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n",
4857 context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
4858 debug_box(src_box
), debug_bo_address(dst_bo_addr
), debug_d3dformat(dst_format
->id
),
4859 dst_x
, dst_y
, dst_z
, dst_row_pitch
, dst_slice_pitch
);
4861 if (src_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
4863 FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location
));
4867 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4868 src_width
= wined3d_texture_get_level_width(src_texture
, src_level
);
4869 src_height
= wined3d_texture_get_level_height(src_texture
, src_level
);
4870 src_depth
= wined3d_texture_get_level_depth(src_texture
, src_level
);
4871 if (src_box
->left
|| src_box
->top
|| src_box
->right
!= src_width
|| src_box
->bottom
!= src_height
4872 || src_box
->front
|| src_box
->back
!= src_depth
)
4874 FIXME("Unhandled source box %s.\n", debug_box(src_box
));
4878 if (dst_bo_addr
->buffer_object
)
4880 FIXME("Unhandled buffer object %#lx.\n", dst_bo_addr
->buffer_object
);
4884 if (dst_format
->id
!= src_texture
->resource
.format
->id
)
4886 FIXME("Unhandled format conversion (%s -> %s).\n",
4887 debug_d3dformat(src_texture
->resource
.format
->id
),
4888 debug_d3dformat(dst_format
->id
));
4892 if (dst_x
|| dst_y
|| dst_z
)
4894 FIXME("Unhandled destination (%u, %u, %u).\n", dst_x
, dst_y
, dst_z
);
4898 if (wined3d_resource_get_sample_count(&src_texture_vk
->t
.resource
) > 1)
4900 FIXME("Not supported for multisample textures.\n");
4904 aspect_mask
= vk_aspect_mask_from_format(src_texture
->resource
.format
);
4905 if (wined3d_popcount(aspect_mask
) > 1)
4907 FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(src_texture
->resource
.format
->id
));
4911 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
4912 if (src_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_1D
)
4913 src_row_pitch
= dst_row_pitch
= 0;
4914 if (src_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_3D
)
4915 src_slice_pitch
= dst_slice_pitch
= 0;
4917 sub_resource
= &src_texture_vk
->t
.sub_resources
[src_sub_resource_idx
];
4918 vk_info
= context_vk
->vk_info
;
4919 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
4921 ERR("Failed to get command buffer.\n");
4925 if (!wined3d_context_vk_create_bo(context_vk
, sub_resource
->size
,
4926 VK_BUFFER_USAGE_TRANSFER_DST_BIT
, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
))
4928 ERR("Failed to create staging bo.\n");
4932 vk_range
.aspectMask
= aspect_mask
;
4933 vk_range
.baseMipLevel
= src_level
;
4934 vk_range
.levelCount
= 1;
4935 vk_range
.baseArrayLayer
= src_sub_resource_idx
/ src_texture_vk
->t
.level_count
;
4936 vk_range
.layerCount
= 1;
4938 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4939 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
4940 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
4941 VK_ACCESS_TRANSFER_READ_BIT
,
4942 src_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
4943 src_texture_vk
->image
.vk_image
, &vk_range
);
4945 region
.bufferOffset
= staging_bo
.buffer_offset
;
4946 region
.bufferRowLength
= 0;
4947 region
.bufferImageHeight
= 0;
4948 region
.imageSubresource
.aspectMask
= vk_range
.aspectMask
;
4949 region
.imageSubresource
.mipLevel
= vk_range
.baseMipLevel
;
4950 region
.imageSubresource
.baseArrayLayer
= vk_range
.baseArrayLayer
;
4951 region
.imageSubresource
.layerCount
= vk_range
.layerCount
;
4952 region
.imageOffset
.x
= 0;
4953 region
.imageOffset
.y
= 0;
4954 region
.imageOffset
.z
= 0;
4955 region
.imageExtent
.width
= src_width
;
4956 region
.imageExtent
.height
= src_height
;
4957 region
.imageExtent
.depth
= src_depth
;
4959 VK_CALL(vkCmdCopyImageToBuffer(vk_command_buffer
, src_texture_vk
->image
.vk_image
,
4960 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, staging_bo
.vk_buffer
, 1, ®ion
));
4962 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4963 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
4964 VK_ACCESS_TRANSFER_READ_BIT
,
4965 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
4966 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
4967 src_texture_vk
->image
.vk_image
, &vk_range
);
4969 wined3d_context_vk_reference_texture(context_vk
, src_texture_vk
);
4970 wined3d_context_vk_reference_bo(context_vk
, &staging_bo
);
4971 wined3d_context_vk_submit_command_buffer(context_vk
, 0, NULL
, NULL
, 0, NULL
);
4972 wined3d_context_vk_wait_command_buffer(context_vk
, src_texture_vk
->image
.command_buffer_id
);
4974 staging_bo_addr
.buffer_object
= (uintptr_t)&staging_bo
;
4975 staging_bo_addr
.addr
= NULL
;
4976 if (!(map_ptr
= wined3d_context_map_bo_address(context
, &staging_bo_addr
,
4977 sub_resource
->size
, WINED3D_MAP_READ
)))
4979 ERR("Failed to map staging bo.\n");
4980 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4984 wined3d_format_copy_data(dst_format
, map_ptr
, src_row_pitch
, src_slice_pitch
,
4985 dst_bo_addr
->addr
, dst_row_pitch
, dst_slice_pitch
, src_box
->right
- src_box
->left
,
4986 src_box
->bottom
- src_box
->top
, src_box
->back
- src_box
->front
);
4988 wined3d_context_unmap_bo_address(context
, &staging_bo_addr
, 0, NULL
);
4989 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4992 static BOOL
wined3d_texture_vk_load_texture(struct wined3d_texture_vk
*texture_vk
,
4993 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
4995 struct wined3d_texture_sub_resource
*sub_resource
;
4996 unsigned int level
, row_pitch
, slice_pitch
;
4997 struct wined3d_bo_address data
;
4998 struct wined3d_box src_box
;
5000 sub_resource
= &texture_vk
->t
.sub_resources
[sub_resource_idx
];
5001 if (!(sub_resource
->locations
& WINED3D_LOCATION_SYSMEM
))
5003 ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource
->locations
));
5007 level
= sub_resource_idx
% texture_vk
->t
.level_count
;
5008 wined3d_texture_get_memory(&texture_vk
->t
, sub_resource_idx
, &data
, WINED3D_LOCATION_SYSMEM
);
5009 wined3d_texture_get_level_box(&texture_vk
->t
, level
, &src_box
);
5010 wined3d_texture_get_pitch(&texture_vk
->t
, level
, &row_pitch
, &slice_pitch
);
5011 wined3d_texture_vk_upload_data(context
, wined3d_const_bo_address(&data
), texture_vk
->t
.resource
.format
,
5012 &src_box
, row_pitch
, slice_pitch
, &texture_vk
->t
, sub_resource_idx
,
5013 WINED3D_LOCATION_TEXTURE_RGB
, 0, 0, 0);
5018 static BOOL
wined3d_texture_vk_load_sysmem(struct wined3d_texture_vk
*texture_vk
,
5019 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
5021 struct wined3d_texture_sub_resource
*sub_resource
;
5022 unsigned int level
, row_pitch
, slice_pitch
;
5023 struct wined3d_bo_address data
;
5024 struct wined3d_box src_box
;
5026 sub_resource
= &texture_vk
->t
.sub_resources
[sub_resource_idx
];
5027 if (!(sub_resource
->locations
& WINED3D_LOCATION_TEXTURE_RGB
))
5029 ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource
->locations
));
5033 level
= sub_resource_idx
% texture_vk
->t
.level_count
;
5034 wined3d_texture_get_memory(&texture_vk
->t
, sub_resource_idx
, &data
, WINED3D_LOCATION_SYSMEM
);
5035 wined3d_texture_get_level_box(&texture_vk
->t
, level
, &src_box
);
5036 wined3d_texture_get_pitch(&texture_vk
->t
, level
, &row_pitch
, &slice_pitch
);
5037 wined3d_texture_vk_download_data(context
, &texture_vk
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
5038 &src_box
, &data
, texture_vk
->t
.resource
.format
, 0, 0, 0, row_pitch
, slice_pitch
);
5043 BOOL
wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk
*texture_vk
,
5044 struct wined3d_context_vk
*context_vk
)
5046 const struct wined3d_format_vk
*format_vk
;
5047 struct wined3d_resource
*resource
;
5048 VkCommandBuffer vk_command_buffer
;
5049 VkImageSubresourceRange vk_range
;
5050 VkImageUsageFlags vk_usage
;
5051 VkImageType vk_image_type
;
5052 unsigned int flags
= 0;
5054 if (texture_vk
->t
.flags
& WINED3D_TEXTURE_RGB_ALLOCATED
)
5057 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
5059 ERR("Failed to get command buffer.\n");
5063 resource
= &texture_vk
->t
.resource
;
5064 format_vk
= wined3d_format_vk(resource
->format
);
5066 if (wined3d_format_is_typeless(&format_vk
->f
) || texture_vk
->t
.swapchain
)
5067 flags
|= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
;
5069 switch (resource
->type
)
5071 case WINED3D_RTYPE_TEXTURE_1D
:
5072 vk_image_type
= VK_IMAGE_TYPE_1D
;
5074 case WINED3D_RTYPE_TEXTURE_2D
:
5075 vk_image_type
= VK_IMAGE_TYPE_2D
;
5076 if (texture_vk
->t
.layer_count
>= 6 && resource
->width
== resource
->height
)
5077 flags
|= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
;
5079 case WINED3D_RTYPE_TEXTURE_3D
:
5080 vk_image_type
= VK_IMAGE_TYPE_3D
;
5081 if (resource
->bind_flags
& (WINED3D_BIND_RENDER_TARGET
| WINED3D_BIND_UNORDERED_ACCESS
))
5082 flags
|= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
;
5085 ERR("Invalid resource type %s.\n", debug_d3dresourcetype(resource
->type
));
5086 vk_image_type
= VK_IMAGE_TYPE_2D
;
5090 vk_usage
= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
;
5091 if (resource
->bind_flags
& WINED3D_BIND_SHADER_RESOURCE
)
5092 vk_usage
|= VK_IMAGE_USAGE_SAMPLED_BIT
;
5093 if (resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)
5094 vk_usage
|= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
5095 if (resource
->bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
5096 vk_usage
|= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
;
5097 if (resource
->bind_flags
& WINED3D_BIND_UNORDERED_ACCESS
)
5098 vk_usage
|= VK_IMAGE_USAGE_STORAGE_BIT
;
5100 texture_vk
->layout
= VK_IMAGE_LAYOUT_GENERAL
;
5101 if (wined3d_popcount(resource
->bind_flags
) == 1)
5103 switch (resource
->bind_flags
)
5105 case WINED3D_BIND_RENDER_TARGET
:
5106 texture_vk
->layout
= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
;
5109 case WINED3D_BIND_DEPTH_STENCIL
:
5110 texture_vk
->layout
= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
;
5113 case WINED3D_BIND_SHADER_RESOURCE
:
5114 texture_vk
->layout
= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
;
5122 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, vk_usage
, format_vk
->vk_format
,
5123 resource
->width
, resource
->height
, resource
->depth
, max(1, wined3d_resource_get_sample_count(resource
)),
5124 texture_vk
->t
.level_count
, texture_vk
->t
.layer_count
, flags
, &texture_vk
->image
))
5129 vk_range
.aspectMask
= vk_aspect_mask_from_format(&format_vk
->f
);
5130 vk_range
.baseMipLevel
= 0;
5131 vk_range
.levelCount
= VK_REMAINING_MIP_LEVELS
;
5132 vk_range
.baseArrayLayer
= 0;
5133 vk_range
.layerCount
= VK_REMAINING_ARRAY_LAYERS
;
5135 wined3d_context_vk_reference_texture(context_vk
, texture_vk
);
5136 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
5137 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
5139 VK_IMAGE_LAYOUT_UNDEFINED
, texture_vk
->layout
,
5140 texture_vk
->image
.vk_image
, &vk_range
);
5142 texture_vk
->t
.flags
|= WINED3D_TEXTURE_RGB_ALLOCATED
;
5144 TRACE("Created image 0x%s, memory 0x%s for texture %p.\n",
5145 wine_dbgstr_longlong(texture_vk
->image
.vk_image
), wine_dbgstr_longlong(texture_vk
->image
.vk_memory
), texture_vk
);
5150 static BOOL
wined3d_texture_vk_prepare_location(struct wined3d_texture
*texture
,
5151 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
5155 case WINED3D_LOCATION_SYSMEM
:
5156 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
5157 : wined3d_resource_prepare_sysmem(&texture
->resource
);
5159 case WINED3D_LOCATION_TEXTURE_RGB
:
5160 return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture
), wined3d_context_vk(context
));
5163 FIXME("Unhandled location %s.\n", wined3d_debug_location(location
));
5168 static BOOL
wined3d_texture_vk_load_location(struct wined3d_texture
*texture
,
5169 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
5171 if (!wined3d_texture_vk_prepare_location(texture
, sub_resource_idx
, context
, location
))
5176 case WINED3D_LOCATION_TEXTURE_RGB
:
5177 return wined3d_texture_vk_load_texture(wined3d_texture_vk(texture
), sub_resource_idx
, context
);
5179 case WINED3D_LOCATION_SYSMEM
:
5180 return wined3d_texture_vk_load_sysmem(wined3d_texture_vk(texture
), sub_resource_idx
, context
);
5183 FIXME("Unimplemented location %s.\n", wined3d_debug_location(location
));
5188 static void wined3d_texture_vk_unload_location(struct wined3d_texture
*texture
,
5189 struct wined3d_context
*context
, unsigned int location
)
5191 struct wined3d_texture_vk
*texture_vk
= wined3d_texture_vk(texture
);
5192 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
5194 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
5198 case WINED3D_LOCATION_TEXTURE_RGB
:
5199 if (texture_vk
->default_image_info
.imageView
)
5201 wined3d_context_vk_destroy_vk_image_view(context_vk
,
5202 texture_vk
->default_image_info
.imageView
, texture_vk
->image
.command_buffer_id
);
5203 texture_vk
->default_image_info
.imageView
= VK_NULL_HANDLE
;
5206 if (texture_vk
->image
.vk_image
)
5207 wined3d_context_vk_destroy_image(context_vk
, &texture_vk
->image
);
5210 case WINED3D_LOCATION_BUFFER
:
5211 case WINED3D_LOCATION_TEXTURE_SRGB
:
5212 case WINED3D_LOCATION_RB_MULTISAMPLE
:
5213 case WINED3D_LOCATION_RB_RESOLVED
:
5217 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
5222 static const struct wined3d_texture_ops wined3d_texture_vk_ops
=
5224 wined3d_texture_vk_prepare_location
,
5225 wined3d_texture_vk_load_location
,
5226 wined3d_texture_vk_unload_location
,
5227 wined3d_texture_vk_upload_data
,
5228 wined3d_texture_vk_download_data
,
5231 HRESULT
wined3d_texture_vk_init(struct wined3d_texture_vk
*texture_vk
, struct wined3d_device
*device
,
5232 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
5233 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
5235 TRACE("texture_vk %p, device %p, desc %p, layer_count %u, "
5236 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
5237 texture_vk
, device
, desc
, layer_count
,
5238 level_count
, flags
, parent
, parent_ops
);
5240 return wined3d_texture_init(&texture_vk
->t
, desc
, layer_count
, level_count
,
5241 flags
, device
, parent
, parent_ops
, &texture_vk
[1], &wined3d_texture_vk_ops
);
5244 void wined3d_texture_vk_barrier(struct wined3d_texture_vk
*texture_vk
,
5245 struct wined3d_context_vk
*context_vk
, uint32_t bind_mask
)
5247 VkImageSubresourceRange vk_range
;
5249 TRACE("texture_vk %p, context_vk %p, bind_mask %s.\n",
5250 texture_vk
, context_vk
, wined3d_debug_bind_flags(bind_mask
));
5252 if (texture_vk
->bind_mask
&& texture_vk
->bind_mask
!= bind_mask
)
5254 TRACE(" %s -> %s.\n",
5255 wined3d_debug_bind_flags(texture_vk
->bind_mask
), wined3d_debug_bind_flags(bind_mask
));
5257 vk_range
.aspectMask
= vk_aspect_mask_from_format(texture_vk
->t
.resource
.format
);
5258 vk_range
.baseMipLevel
= 0;
5259 vk_range
.levelCount
= VK_REMAINING_MIP_LEVELS
;
5260 vk_range
.baseArrayLayer
= 0;
5261 vk_range
.layerCount
= VK_REMAINING_ARRAY_LAYERS
;
5263 wined3d_context_vk_image_barrier(context_vk
, wined3d_context_vk_get_command_buffer(context_vk
),
5264 vk_pipeline_stage_mask_from_bind_flags(texture_vk
->bind_mask
),
5265 vk_pipeline_stage_mask_from_bind_flags(bind_mask
),
5266 vk_access_mask_from_bind_flags(texture_vk
->bind_mask
), vk_access_mask_from_bind_flags(bind_mask
),
5267 texture_vk
->layout
, texture_vk
->layout
, texture_vk
->image
.vk_image
, &vk_range
);
5269 texture_vk
->bind_mask
= bind_mask
;
5272 static void ffp_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
5274 struct wined3d_blitter
*next
;
5276 if ((next
= blitter
->next
))
5277 next
->ops
->blitter_destroy(next
, context
);
5282 static bool ffp_blit_supported(enum wined3d_blit_op blit_op
, const struct wined3d_context
*context
,
5283 const struct wined3d_resource
*src_resource
, DWORD src_location
,
5284 const struct wined3d_resource
*dst_resource
, DWORD dst_location
)
5286 const struct wined3d_format
*src_format
= src_resource
->format
;
5287 const struct wined3d_format
*dst_format
= dst_resource
->format
;
5290 if (src_resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
5293 decompress
= (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
5294 && !(dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
);
5295 if (!decompress
&& !(src_resource
->access
& dst_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
5297 TRACE("Source or destination resource is not GPU accessible.\n");
5301 if (blit_op
== WINED3D_BLIT_OP_RAW_BLIT
&& dst_format
->id
== src_format
->id
)
5303 if (dst_format
->depth_size
|| dst_format
->stencil_size
)
5304 blit_op
= WINED3D_BLIT_OP_DEPTH_BLIT
;
5306 blit_op
= WINED3D_BLIT_OP_COLOR_BLIT
;
5311 case WINED3D_BLIT_OP_COLOR_BLIT_CKEY
:
5312 if (context
->d3d_info
->shader_color_key
)
5314 TRACE("Colour keying requires converted textures.\n");
5317 case WINED3D_BLIT_OP_COLOR_BLIT
:
5318 case WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
:
5319 if (!wined3d_context_gl_const(context
)->gl_info
->supported
[WINED3D_GL_LEGACY_CONTEXT
])
5324 TRACE("Checking support for fixup:\n");
5325 dump_color_fixup_desc(src_format
->color_fixup
);
5328 /* We only support identity conversions. */
5329 if (!is_identity_fixup(src_format
->color_fixup
)
5330 || !is_identity_fixup(dst_format
->color_fixup
))
5332 if (wined3d_settings
.offscreen_rendering_mode
== ORM_BACKBUFFER
5333 && dst_format
->id
== src_format
->id
&& dst_location
== WINED3D_LOCATION_DRAWABLE
)
5335 WARN("Claiming fixup support because of ORM_BACKBUFFER.\n");
5339 TRACE("Fixups are not supported.\n");
5344 if (!(dst_resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
))
5346 TRACE("Can only blit to render targets.\n");
5352 TRACE("Unsupported blit operation %#x.\n", blit_op
);
5357 static bool is_full_clear(const struct wined3d_rendertarget_view
*rtv
, const RECT
*draw_rect
, const RECT
*clear_rect
)
5359 unsigned int height
= rtv
->height
;
5360 unsigned int width
= rtv
->width
;
5362 /* partial draw rect */
5363 if (draw_rect
->left
|| draw_rect
->top
|| draw_rect
->right
< width
|| draw_rect
->bottom
< height
)
5366 /* partial clear rect */
5367 if (clear_rect
&& (clear_rect
->left
> 0 || clear_rect
->top
> 0
5368 || clear_rect
->right
< width
|| clear_rect
->bottom
< height
))
5374 static void ffp_blitter_clear_rendertargets(struct wined3d_device
*device
, unsigned int rt_count
,
5375 const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rect
, const RECT
*draw_rect
,
5376 uint32_t flags
, const struct wined3d_color
*colour
, float depth
, unsigned int stencil
)
5378 struct wined3d_rendertarget_view
*rtv
= rt_count
? fb
->render_targets
[0] : NULL
;
5379 struct wined3d_rendertarget_view
*dsv
= fb
->depth_stencil
;
5380 const struct wined3d_state
*state
= &device
->cs
->state
;
5381 struct wined3d_texture
*depth_stencil
= NULL
;
5382 unsigned int drawable_width
, drawable_height
;
5383 const struct wined3d_gl_info
*gl_info
;
5384 struct wined3d_context_gl
*context_gl
;
5385 struct wined3d_texture
*target
= NULL
;
5386 struct wined3d_color colour_srgb
;
5387 struct wined3d_context
*context
;
5388 GLbitfield clear_mask
= 0;
5389 bool render_offscreen
;
5392 if (rtv
&& rtv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
5394 target
= texture_from_resource(rtv
->resource
);
5395 context
= context_acquire(device
, target
, rtv
->sub_resource_idx
);
5399 context
= context_acquire(device
, NULL
, 0);
5401 context_gl
= wined3d_context_gl(context
);
5403 if (dsv
&& dsv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
5404 depth_stencil
= texture_from_resource(dsv
->resource
);
5406 if (!context_gl
->valid
)
5408 context_release(context
);
5409 WARN("Invalid context, skipping clear.\n");
5412 gl_info
= context_gl
->gl_info
;
5414 /* When we're clearing parts of the drawable, make sure that the target
5415 * surface is well up to date in the drawable. After the clear we'll mark
5416 * the drawable up to date, so we have to make sure that this is true for
5417 * the cleared parts, and the untouched parts.
5419 * If we're clearing the whole target there is no need to copy it into the
5420 * drawable, it will be overwritten anyway. If we're not clearing the
5421 * colour buffer we don't have to copy either since we're not going to set
5422 * the drawable up to date. We have to check all settings that limit the
5423 * clear area though. Do not bother checking all this if the destination
5424 * surface is in the drawable anyway. */
5425 for (i
= 0; i
< rt_count
; ++i
)
5427 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
5429 if (rtv
&& rtv
->format
->id
!= WINED3DFMT_NULL
)
5431 if (flags
& WINED3DCLEAR_TARGET
&& !is_full_clear(rtv
, draw_rect
, rect_count
? clear_rect
: NULL
))
5432 wined3d_rendertarget_view_load_location(rtv
, context
, rtv
->resource
->draw_binding
);
5434 wined3d_rendertarget_view_prepare_location(rtv
, context
, rtv
->resource
->draw_binding
);
5440 render_offscreen
= context
->render_offscreen
;
5441 wined3d_rendertarget_view_get_drawable_size(rtv
, context
, &drawable_width
, &drawable_height
);
5445 unsigned int ds_level
= dsv
->sub_resource_idx
% depth_stencil
->level_count
;
5447 render_offscreen
= true;
5448 drawable_width
= wined3d_texture_get_level_pow2_width(depth_stencil
, ds_level
);
5449 drawable_height
= wined3d_texture_get_level_pow2_height(depth_stencil
, ds_level
);
5454 DWORD ds_location
= render_offscreen
? dsv
->resource
->draw_binding
: WINED3D_LOCATION_DRAWABLE
;
5456 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)
5457 && !is_full_clear(dsv
, draw_rect
, rect_count
? clear_rect
: NULL
))
5458 wined3d_rendertarget_view_load_location(dsv
, context
, ds_location
);
5460 wined3d_rendertarget_view_prepare_location(dsv
, context
, ds_location
);
5462 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5464 wined3d_rendertarget_view_validate_location(dsv
, ds_location
);
5465 wined3d_rendertarget_view_invalidate_location(dsv
, ~ds_location
);
5469 if (!wined3d_context_gl_apply_clear_state(context_gl
, state
, rt_count
, fb
))
5471 context_release(context
);
5472 WARN("Failed to apply clear state, skipping clear.\n");
5476 /* Only set the values up once, as they are not changing. */
5477 if (flags
& WINED3DCLEAR_STENCIL
)
5479 if (gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
5480 gl_info
->gl_ops
.gl
.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
5481 gl_info
->gl_ops
.gl
.p_glStencilMask(~0u);
5482 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
5483 gl_info
->gl_ops
.gl
.p_glClearStencil(stencil
);
5484 checkGLcall("glClearStencil");
5485 clear_mask
= clear_mask
| GL_STENCIL_BUFFER_BIT
;
5488 if (flags
& WINED3DCLEAR_ZBUFFER
)
5490 gl_info
->gl_ops
.gl
.p_glDepthMask(GL_TRUE
);
5491 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
5492 if (gl_info
->supported
[ARB_ES2_COMPATIBILITY
])
5493 GL_EXTCALL(glClearDepthf(depth
));
5495 gl_info
->gl_ops
.gl
.p_glClearDepth(depth
);
5496 checkGLcall("glClearDepth");
5497 clear_mask
= clear_mask
| GL_DEPTH_BUFFER_BIT
;
5500 if (flags
& WINED3DCLEAR_TARGET
)
5502 for (i
= 0; i
< rt_count
; ++i
)
5504 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
5509 if (rtv
->resource
->type
== WINED3D_RTYPE_BUFFER
)
5511 FIXME("Not supported on buffer resources.\n");
5515 wined3d_rendertarget_view_validate_location(rtv
, rtv
->resource
->draw_binding
);
5516 wined3d_rendertarget_view_invalidate_location(rtv
, ~rtv
->resource
->draw_binding
);
5519 if (!gl_info
->supported
[ARB_FRAMEBUFFER_SRGB
] && needs_srgb_write(context
->d3d_info
, state
, fb
))
5522 WARN("Clearing multiple sRGB render targets without GL_ARB_framebuffer_sRGB "
5523 "support, this might cause graphical issues.\n");
5525 wined3d_colour_srgb_from_linear(&colour_srgb
, colour
);
5526 colour
= &colour_srgb
;
5529 gl_info
->gl_ops
.gl
.p_glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5530 context_invalidate_state(context
, STATE_BLEND
);
5531 gl_info
->gl_ops
.gl
.p_glClearColor(colour
->r
, colour
->g
, colour
->b
, colour
->a
);
5532 checkGLcall("glClearColor");
5533 clear_mask
= clear_mask
| GL_COLOR_BUFFER_BIT
;
5538 if (render_offscreen
)
5540 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, draw_rect
->top
,
5541 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
5545 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, drawable_height
- draw_rect
->bottom
,
5546 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
5548 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
5554 /* Now process each rect in turn. */
5555 for (i
= 0; i
< rect_count
; ++i
)
5557 /* Note that GL uses lower left, width/height. */
5558 IntersectRect(¤t_rect
, draw_rect
, &clear_rect
[i
]);
5560 TRACE("clear_rect[%u] %s, current_rect %s.\n", i
,
5561 wine_dbgstr_rect(&clear_rect
[i
]),
5562 wine_dbgstr_rect(¤t_rect
));
5564 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored
5565 * silently. The rectangle is not cleared, no error is returned,
5566 * but further rectangles are still cleared if they are valid. */
5567 if (current_rect
.left
> current_rect
.right
|| current_rect
.top
> current_rect
.bottom
)
5569 TRACE("Rectangle with negative dimensions, ignoring.\n");
5573 if (render_offscreen
)
5575 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, current_rect
.top
,
5576 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
5580 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, drawable_height
- current_rect
.bottom
,
5581 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
5583 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
5586 context
->scissor_rect_count
= WINED3D_MAX_VIEWPORTS
;
5587 checkGLcall("clear");
5589 if (flags
& WINED3DCLEAR_TARGET
&& target
->swapchain
&& target
->swapchain
->front_buffer
== target
)
5590 gl_info
->gl_ops
.gl
.p_glFlush();
5592 context_release(context
);
5595 static bool blitter_use_cpu_clear(struct wined3d_rendertarget_view
*view
)
5597 struct wined3d_resource
*resource
;
5598 struct wined3d_texture
*texture
;
5601 resource
= view
->resource
;
5602 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
5603 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
);
5605 texture
= texture_from_resource(resource
);
5606 locations
= texture
->sub_resources
[view
->sub_resource_idx
].locations
;
5607 if (locations
& (resource
->map_binding
| WINED3D_LOCATION_DISCARDED
))
5608 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
5609 || (texture
->flags
& WINED3D_TEXTURE_PIN_SYSMEM
);
5611 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
5612 && !(texture
->flags
& WINED3D_TEXTURE_CONVERTED
);
5615 static void ffp_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
5616 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
5617 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
5619 struct wined3d_rendertarget_view
*view
, *previous
= NULL
;
5620 bool have_identical_size
= TRUE
;
5621 struct wined3d_fb_state tmp_fb
;
5622 unsigned int next_rt_count
= 0;
5623 struct wined3d_blitter
*next
;
5624 DWORD next_flags
= 0;
5627 if (flags
& WINED3DCLEAR_TARGET
)
5629 for (i
= 0; i
< rt_count
; ++i
)
5631 if (!(view
= fb
->render_targets
[i
]))
5634 if (blitter_use_cpu_clear(view
)
5635 || (!(view
->resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)
5636 && (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
5637 || !(view
->format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE
))))
5639 next_flags
|= WINED3DCLEAR_TARGET
;
5640 flags
&= ~WINED3DCLEAR_TARGET
;
5641 next_rt_count
= rt_count
;
5646 /* FIXME: We should reject colour fills on formats with fixups,
5647 * but this would break P8 colour fills for example. */
5651 if ((flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)) && (view
= fb
->depth_stencil
)
5652 && (!view
->format
->depth_size
|| (flags
& WINED3DCLEAR_ZBUFFER
))
5653 && (!view
->format
->stencil_size
|| (flags
& WINED3DCLEAR_STENCIL
))
5654 && blitter_use_cpu_clear(view
))
5656 next_flags
|= flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
5657 flags
&= ~(WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
5662 for (i
= 0; i
< rt_count
; ++i
)
5664 if (!(view
= fb
->render_targets
[i
]))
5667 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
5668 have_identical_size
= false;
5671 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5673 view
= fb
->depth_stencil
;
5675 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
5676 have_identical_size
= false;
5679 if (have_identical_size
)
5681 ffp_blitter_clear_rendertargets(device
, rt_count
, fb
, rect_count
,
5682 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
5686 for (i
= 0; i
< rt_count
; ++i
)
5688 if (!(view
= fb
->render_targets
[i
]))
5691 tmp_fb
.render_targets
[0] = view
;
5692 tmp_fb
.depth_stencil
= NULL
;
5693 ffp_blitter_clear_rendertargets(device
, 1, &tmp_fb
, rect_count
,
5694 clear_rects
, draw_rect
, WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
5696 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5698 tmp_fb
.render_targets
[0] = NULL
;
5699 tmp_fb
.depth_stencil
= fb
->depth_stencil
;
5700 ffp_blitter_clear_rendertargets(device
, 0, &tmp_fb
, rect_count
,
5701 clear_rects
, draw_rect
, flags
& ~WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
5706 if (next_flags
&& (next
= blitter
->next
))
5707 next
->ops
->blitter_clear(next
, device
, next_rt_count
, fb
, rect_count
,
5708 clear_rects
, draw_rect
, next_flags
, colour
, depth
, stencil
);
5711 static DWORD
ffp_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
5712 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
5713 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
5714 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
5715 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
5716 const struct wined3d_format
*resolve_format
)
5718 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
5719 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
5720 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
5721 struct wined3d_resource
*src_resource
, *dst_resource
;
5722 struct wined3d_texture
*staging_texture
= NULL
;
5723 struct wined3d_color_key old_blt_key
;
5724 struct wined3d_device
*device
;
5725 struct wined3d_blitter
*next
;
5726 DWORD old_colour_key_flags
;
5729 src_resource
= &src_texture
->resource
;
5730 dst_resource
= &dst_texture
->resource
;
5731 device
= dst_resource
->device
;
5733 if (!ffp_blit_supported(op
, context
, src_resource
, src_location
, dst_resource
, dst_location
))
5735 if ((next
= blitter
->next
))
5736 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
5737 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
5741 TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
5742 src_texture
, src_sub_resource_idx
, dst_texture
, dst_sub_resource_idx
);
5744 old_blt_key
= src_texture
->async
.src_blt_color_key
;
5745 old_colour_key_flags
= src_texture
->async
.color_key_flags
;
5746 wined3d_texture_set_color_key(src_texture
, WINED3D_CKEY_SRC_BLT
, colour_key
);
5748 if (!(src_texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_GPU
))
5750 struct wined3d_resource_desc desc
;
5751 struct wined3d_box upload_box
;
5752 unsigned int src_level
;
5755 TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
5757 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
5758 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
5759 desc
.format
= src_texture
->resource
.format
->id
;
5760 desc
.multisample_type
= src_texture
->resource
.multisample_type
;
5761 desc
.multisample_quality
= src_texture
->resource
.multisample_quality
;
5762 desc
.usage
= WINED3DUSAGE_PRIVATE
;
5763 desc
.bind_flags
= 0;
5764 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
5765 desc
.width
= wined3d_texture_get_level_width(src_texture
, src_level
);
5766 desc
.height
= wined3d_texture_get_level_height(src_texture
, src_level
);
5770 if (FAILED(hr
= wined3d_texture_create(device
, &desc
, 1, 1, 0,
5771 NULL
, NULL
, &wined3d_null_parent_ops
, &staging_texture
)))
5773 ERR("Failed to create staging texture, hr %#x.\n", hr
);
5774 return dst_location
;
5777 wined3d_box_set(&upload_box
, 0, 0, desc
.width
, desc
.height
, 0, desc
.depth
);
5778 wined3d_texture_upload_from_texture(staging_texture
, 0, 0, 0, 0,
5779 src_texture
, src_sub_resource_idx
, &upload_box
);
5781 src_texture
= staging_texture
;
5782 src_texture_gl
= wined3d_texture_gl(src_texture
);
5783 src_sub_resource_idx
= 0;
5787 /* Make sure the surface is up-to-date. This should probably use
5788 * surface_load_location() and worry about the destination surface
5789 * too, unless we're overwriting it completely. */
5790 wined3d_texture_load(src_texture
, context
, FALSE
);
5793 wined3d_context_gl_apply_ffp_blit_state(context_gl
, device
);
5795 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
5798 wined3d_texture_translate_drawable_coords(dst_texture
, context_gl
->window
, &r
);
5802 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
5806 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
5808 TRACE("Destination texture %p is onscreen.\n", dst_texture
);
5809 buffer
= wined3d_texture_get_gl_buffer(dst_texture
);
5813 TRACE("Destination texture %p is offscreen.\n", dst_texture
);
5814 buffer
= GL_COLOR_ATTACHMENT0
;
5816 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_DRAW_FRAMEBUFFER
,
5817 dst_resource
, dst_sub_resource_idx
, NULL
, 0, dst_location
);
5818 wined3d_context_gl_set_draw_buffer(context_gl
, buffer
);
5819 wined3d_context_gl_check_fbo_status(context_gl
, GL_DRAW_FRAMEBUFFER
);
5820 context_invalidate_state(context
, STATE_FRAMEBUFFER
);
5823 gl_info
->gl_ops
.gl
.p_glEnable(src_texture_gl
->target
);
5824 checkGLcall("glEnable(target)");
5826 if (op
== WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
|| colour_key
)
5828 gl_info
->gl_ops
.gl
.p_glEnable(GL_ALPHA_TEST
);
5829 checkGLcall("glEnable(GL_ALPHA_TEST)");
5834 /* For P8 surfaces, the alpha component contains the palette index.
5835 * Which means that the colourkey is one of the palette entries. In
5836 * other cases pixels that should be masked away have alpha set to 0. */
5837 if (src_texture
->resource
.format
->id
== WINED3DFMT_P8_UINT
)
5838 gl_info
->gl_ops
.gl
.p_glAlphaFunc(GL_NOTEQUAL
,
5839 (float)src_texture
->async
.src_blt_color_key
.color_space_low_value
/ 255.0f
);
5841 gl_info
->gl_ops
.gl
.p_glAlphaFunc(GL_NOTEQUAL
, 0.0f
);
5842 checkGLcall("glAlphaFunc");
5845 wined3d_context_gl_draw_textured_quad(context_gl
, src_texture_gl
,
5846 src_sub_resource_idx
, src_rect
, dst_rect
, filter
);
5848 if (op
== WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
|| colour_key
)
5850 gl_info
->gl_ops
.gl
.p_glDisable(GL_ALPHA_TEST
);
5851 checkGLcall("glDisable(GL_ALPHA_TEST)");
5854 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_2D
);
5855 checkGLcall("glDisable(GL_TEXTURE_2D)");
5856 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
])
5858 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
5859 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
5861 if (gl_info
->supported
[ARB_TEXTURE_RECTANGLE
])
5863 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_RECTANGLE_ARB
);
5864 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
5867 if (dst_texture
->swapchain
&& dst_texture
->swapchain
->front_buffer
== dst_texture
)
5868 gl_info
->gl_ops
.gl
.p_glFlush();
5870 /* Restore the colour key parameters */
5871 wined3d_texture_set_color_key(src_texture
, WINED3D_CKEY_SRC_BLT
,
5872 (old_colour_key_flags
& WINED3D_CKEY_SRC_BLT
) ? &old_blt_key
: NULL
);
5874 if (staging_texture
)
5875 wined3d_texture_decref(staging_texture
);
5877 return dst_location
;
5880 static const struct wined3d_blitter_ops ffp_blitter_ops
=
5882 ffp_blitter_destroy
,
5887 void wined3d_ffp_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
5889 struct wined3d_blitter
*blitter
;
5891 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
5894 TRACE("Created blitter %p.\n", blitter
);
5896 blitter
->ops
= &ffp_blitter_ops
;
5897 blitter
->next
= *next
;
5901 static void fbo_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
5903 struct wined3d_blitter
*next
;
5905 if ((next
= blitter
->next
))
5906 next
->ops
->blitter_destroy(next
, context
);
5911 static void fbo_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
5912 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
5913 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
5915 struct wined3d_blitter
*next
;
5917 if ((next
= blitter
->next
))
5918 next
->ops
->blitter_clear(next
, device
, rt_count
, fb
, rect_count
,
5919 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
5922 static DWORD
fbo_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
5923 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
5924 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
5925 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
5926 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
5927 const struct wined3d_format
*resolve_format
)
5929 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
5930 struct wined3d_resource
*src_resource
, *dst_resource
;
5931 enum wined3d_blit_op blit_op
= op
;
5932 struct wined3d_device
*device
;
5933 struct wined3d_blitter
*next
;
5935 TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, "
5936 "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, "
5937 "colour_key %p, filter %s, resolve_format %p.\n",
5938 blitter
, op
, context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
5939 wine_dbgstr_rect(src_rect
), dst_texture
, dst_sub_resource_idx
, wined3d_debug_location(dst_location
),
5940 wine_dbgstr_rect(dst_rect
), colour_key
, debug_d3dtexturefiltertype(filter
), resolve_format
);
5942 src_resource
= &src_texture
->resource
;
5943 dst_resource
= &dst_texture
->resource
;
5945 device
= dst_resource
->device
;
5947 if (blit_op
== WINED3D_BLIT_OP_RAW_BLIT
&& dst_resource
->format
->id
== src_resource
->format
->id
)
5949 if (dst_resource
->format
->depth_size
|| dst_resource
->format
->stencil_size
)
5950 blit_op
= WINED3D_BLIT_OP_DEPTH_BLIT
;
5952 blit_op
= WINED3D_BLIT_OP_COLOR_BLIT
;
5955 if (!fbo_blitter_supported(blit_op
, context_gl
->gl_info
,
5956 src_resource
, src_location
, dst_resource
, dst_location
))
5958 if (!(next
= blitter
->next
))
5960 ERR("No blitter to handle blit op %#x.\n", op
);
5961 return dst_location
;
5964 TRACE("Forwarding to blitter %p.\n", next
);
5965 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
5966 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
5970 if (blit_op
== WINED3D_BLIT_OP_COLOR_BLIT
)
5972 TRACE("Colour blit.\n");
5973 texture2d_blt_fbo(device
, context
, filter
, src_texture
, src_sub_resource_idx
, src_location
,
5974 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, resolve_format
);
5975 return dst_location
;
5978 if (blit_op
== WINED3D_BLIT_OP_DEPTH_BLIT
)
5980 TRACE("Depth/stencil blit.\n");
5981 texture2d_depth_blt_fbo(device
, context
, src_texture
, src_sub_resource_idx
, src_location
,
5982 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
);
5983 return dst_location
;
5986 ERR("This blitter does not implement blit op %#x.\n", blit_op
);
5987 return dst_location
;
5990 static const struct wined3d_blitter_ops fbo_blitter_ops
=
5992 fbo_blitter_destroy
,
5997 void wined3d_fbo_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
5999 struct wined3d_blitter
*blitter
;
6001 if ((wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) || !gl_info
->fbo_ops
.glBlitFramebuffer
)
6004 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6007 TRACE("Created blitter %p.\n", blitter
);
6009 blitter
->ops
= &fbo_blitter_ops
;
6010 blitter
->next
= *next
;
6014 static void raw_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
6016 struct wined3d_blitter
*next
;
6018 if ((next
= blitter
->next
))
6019 next
->ops
->blitter_destroy(next
, context
);
6024 static void raw_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
6025 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
6026 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
6028 struct wined3d_blitter
*next
;
6030 if (!(next
= blitter
->next
))
6032 ERR("No blitter to handle clear.\n");
6036 TRACE("Forwarding to blitter %p.\n", next
);
6037 next
->ops
->blitter_clear(next
, device
, rt_count
, fb
, rect_count
,
6038 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
6041 static DWORD
raw_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
6042 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
6043 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
6044 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
6045 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
6046 const struct wined3d_format
*resolve_format
)
6048 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
6049 struct wined3d_texture_gl
*dst_texture_gl
= wined3d_texture_gl(dst_texture
);
6050 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
6051 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
6052 unsigned int src_level
, src_layer
, dst_level
, dst_layer
;
6053 struct wined3d_blitter
*next
;
6054 GLuint src_name
, dst_name
;
6055 bool src_ds
, dst_ds
;
6058 src_ds
= src_texture
->resource
.format
->depth_size
|| src_texture
->resource
.format
->stencil_size
;
6059 dst_ds
= dst_texture
->resource
.format
->depth_size
|| dst_texture
->resource
.format
->stencil_size
;
6061 /* If we would need to copy from a renderbuffer or drawable, we'd probably
6062 * be better off using the FBO blitter directly, since we'd need to use it
6063 * to copy the resource contents to the texture anyway.
6065 * We also can't copy between depth/stencil and colour resources, since
6066 * the formats are considered incompatible in OpenGL. */
6067 if (op
!= WINED3D_BLIT_OP_RAW_BLIT
|| (src_ds
!= dst_ds
)
6068 || (src_texture
->resource
.format
->id
== dst_texture
->resource
.format
->id
6069 && (!(src_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
))
6070 || !(dst_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
)))))
6072 if (!(next
= blitter
->next
))
6074 ERR("No blitter to handle blit op %#x.\n", op
);
6075 return dst_location
;
6078 TRACE("Forwarding to blitter %p.\n", next
);
6079 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6080 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
6084 TRACE("Blit using ARB_copy_image.\n");
6086 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
6087 src_layer
= src_sub_resource_idx
/ src_texture
->level_count
;
6089 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
6090 dst_layer
= dst_sub_resource_idx
/ dst_texture
->level_count
;
6092 location
= src_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
6094 location
= src_texture
->flags
& WINED3D_TEXTURE_IS_SRGB
6095 ? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
6096 if (!wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, location
))
6097 ERR("Failed to load the source sub-resource into %s.\n", wined3d_debug_location(location
));
6098 src_name
= wined3d_texture_gl_get_texture_name(src_texture_gl
,
6099 context
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
6101 location
= dst_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
6103 location
= dst_texture
->flags
& WINED3D_TEXTURE_IS_SRGB
6104 ? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
6105 if (wined3d_texture_is_full_rect(dst_texture
, dst_level
, dst_rect
))
6107 if (!wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, location
))
6108 ERR("Failed to prepare the destination sub-resource into %s.\n", wined3d_debug_location(location
));
6112 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, location
))
6113 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(location
));
6115 dst_name
= wined3d_texture_gl_get_texture_name(dst_texture_gl
,
6116 context
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
6118 GL_EXTCALL(glCopyImageSubData(src_name
, src_texture_gl
->target
, src_level
,
6119 src_rect
->left
, src_rect
->top
, src_layer
, dst_name
, dst_texture_gl
->target
, dst_level
,
6120 dst_rect
->left
, dst_rect
->top
, dst_layer
, src_rect
->right
- src_rect
->left
,
6121 src_rect
->bottom
- src_rect
->top
, 1));
6122 checkGLcall("copy image data");
6124 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, location
);
6125 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~location
);
6126 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
))
6127 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location
));
6129 return dst_location
| location
;
6132 static const struct wined3d_blitter_ops raw_blitter_ops
=
6134 raw_blitter_destroy
,
6139 void wined3d_raw_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
6141 struct wined3d_blitter
*blitter
;
6143 if (!gl_info
->supported
[ARB_COPY_IMAGE
])
6146 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6149 TRACE("Created blitter %p.\n", blitter
);
6151 blitter
->ops
= &raw_blitter_ops
;
6152 blitter
->next
= *next
;
6156 static void vk_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
6158 struct wined3d_blitter
*next
;
6160 TRACE("blitter %p, context %p.\n", blitter
, context
);
6162 if ((next
= blitter
->next
))
6163 next
->ops
->blitter_destroy(next
, context
);
6168 static void vk_blitter_clear_rendertargets(struct wined3d_context_vk
*context_vk
, unsigned int rt_count
,
6169 const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
, const RECT
*draw_rect
,
6170 uint32_t flags
, const struct wined3d_color
*colour
, float depth
, unsigned int stencil
)
6172 VkClearValue clear_values
[WINED3D_MAX_RENDER_TARGETS
+ 1];
6173 VkImageView views
[WINED3D_MAX_RENDER_TARGETS
+ 1];
6174 struct wined3d_rendertarget_view_vk
*rtv_vk
;
6175 struct wined3d_rendertarget_view
*view
;
6176 const struct wined3d_vk_info
*vk_info
;
6177 struct wined3d_device_vk
*device_vk
;
6178 VkCommandBuffer vk_command_buffer
;
6179 VkRenderPassBeginInfo begin_desc
;
6180 unsigned int i
, attachment_count
;
6181 VkFramebufferCreateInfo fb_desc
;
6182 VkFramebuffer vk_framebuffer
;
6183 VkRenderPass vk_render_pass
;
6184 bool depth_stencil
= false;
6185 unsigned int layer_count
;
6186 VkClearColorValue
*c
;
6190 TRACE("context_vk %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, "
6191 "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n",
6192 context_vk
, rt_count
, fb
, rect_count
, clear_rects
,
6193 wine_dbgstr_rect(draw_rect
), flags
, debug_color(colour
), depth
, stencil
);
6195 device_vk
= wined3d_device_vk(context_vk
->c
.device
);
6196 vk_info
= context_vk
->vk_info
;
6198 if (!(flags
& WINED3DCLEAR_TARGET
))
6201 for (i
= 0, attachment_count
= 0, layer_count
= 1; i
< rt_count
; ++i
)
6203 if (!(view
= fb
->render_targets
[i
]))
6206 if (!is_full_clear(view
, draw_rect
, clear_rects
))
6207 wined3d_rendertarget_view_load_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6209 wined3d_rendertarget_view_prepare_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6210 wined3d_rendertarget_view_validate_location(view
, view
->resource
->draw_binding
);
6211 wined3d_rendertarget_view_invalidate_location(view
, ~view
->resource
->draw_binding
);
6213 rtv_vk
= wined3d_rendertarget_view_vk(view
);
6214 views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
6215 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_RENDER_TARGET
);
6217 c
= &clear_values
[attachment_count
].color
;
6218 if (view
->format_flags
& WINED3DFMT_FLAG_INTEGER
)
6220 c
->int32
[0] = colour
->r
;
6221 c
->int32
[1] = colour
->g
;
6222 c
->int32
[2] = colour
->b
;
6223 c
->int32
[3] = colour
->a
;
6227 c
->float32
[0] = colour
->r
;
6228 c
->float32
[1] = colour
->g
;
6229 c
->float32
[2] = colour
->b
;
6230 c
->float32
[3] = colour
->a
;
6233 if (view
->layer_count
> layer_count
)
6234 layer_count
= view
->layer_count
;
6239 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && (view
= fb
->depth_stencil
))
6241 if (!is_full_clear(view
, draw_rect
, clear_rects
))
6242 wined3d_rendertarget_view_load_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6244 wined3d_rendertarget_view_prepare_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6245 wined3d_rendertarget_view_validate_location(view
, view
->resource
->draw_binding
);
6246 wined3d_rendertarget_view_invalidate_location(view
, ~view
->resource
->draw_binding
);
6248 rtv_vk
= wined3d_rendertarget_view_vk(view
);
6249 views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
6250 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_DEPTH_STENCIL
);
6252 clear_values
[attachment_count
].depthStencil
.depth
= depth
;
6253 clear_values
[attachment_count
].depthStencil
.stencil
= stencil
;
6255 if (view
->layer_count
> layer_count
)
6256 layer_count
= view
->layer_count
;
6258 depth_stencil
= true;
6262 if (!attachment_count
)
6265 if (!(vk_render_pass
= wined3d_context_vk_get_render_pass(context_vk
, fb
,
6266 rt_count
, flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
), flags
)))
6268 ERR("Failed to get render pass.\n");
6272 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
6274 ERR("Failed to get command buffer.\n");
6278 fb_desc
.sType
= VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
;
6279 fb_desc
.pNext
= NULL
;
6281 fb_desc
.renderPass
= vk_render_pass
;
6282 fb_desc
.attachmentCount
= attachment_count
;
6283 fb_desc
.pAttachments
= views
;
6284 fb_desc
.width
= draw_rect
->right
- draw_rect
->left
;
6285 fb_desc
.height
= draw_rect
->bottom
- draw_rect
->top
;
6286 fb_desc
.layers
= layer_count
;
6287 if ((vr
= VK_CALL(vkCreateFramebuffer(device_vk
->vk_device
, &fb_desc
, NULL
, &vk_framebuffer
))) < 0)
6289 ERR("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr
));
6293 begin_desc
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
;
6294 begin_desc
.pNext
= NULL
;
6295 begin_desc
.renderPass
= vk_render_pass
;
6296 begin_desc
.framebuffer
= vk_framebuffer
;
6297 begin_desc
.clearValueCount
= attachment_count
;
6298 begin_desc
.pClearValues
= clear_values
;
6300 wined3d_context_vk_end_current_render_pass(context_vk
);
6302 for (i
= 0; i
< rect_count
; ++i
)
6304 r
.left
= max(clear_rects
[i
].left
, draw_rect
->left
);
6305 r
.top
= max(clear_rects
[i
].top
, draw_rect
->top
);
6306 r
.right
= min(clear_rects
[i
].right
, draw_rect
->right
);
6307 r
.bottom
= min(clear_rects
[i
].bottom
, draw_rect
->bottom
);
6309 if (r
.left
>= r
.right
|| r
.top
>= r
.bottom
)
6312 begin_desc
.renderArea
.offset
.x
= r
.left
;
6313 begin_desc
.renderArea
.offset
.y
= r
.top
;
6314 begin_desc
.renderArea
.extent
.width
= r
.right
- r
.left
;
6315 begin_desc
.renderArea
.extent
.height
= r
.bottom
- r
.top
;
6316 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer
, &begin_desc
, VK_SUBPASS_CONTENTS_INLINE
));
6317 VK_CALL(vkCmdEndRenderPass(vk_command_buffer
));
6320 wined3d_context_vk_destroy_vk_framebuffer(context_vk
, vk_framebuffer
, context_vk
->current_command_buffer
.id
);
6322 for (i
= 0; i
< rt_count
; ++i
)
6324 if (!(view
= fb
->render_targets
[i
]))
6327 wined3d_context_vk_reference_rendertarget_view(context_vk
, wined3d_rendertarget_view_vk(view
));
6332 view
= fb
->depth_stencil
;
6333 wined3d_context_vk_reference_rendertarget_view(context_vk
, wined3d_rendertarget_view_vk(view
));
6337 static void vk_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
6338 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
6339 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
6341 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(device
);
6342 struct wined3d_rendertarget_view
*view
, *previous
= NULL
;
6343 struct wined3d_context_vk
*context_vk
;
6344 bool have_identical_size
= true;
6345 struct wined3d_fb_state tmp_fb
;
6346 unsigned int next_rt_count
= 0;
6347 struct wined3d_blitter
*next
;
6348 uint32_t next_flags
= 0;
6351 TRACE("blitter %p, device %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, "
6352 "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n",
6353 blitter
, device
, rt_count
, fb
, rect_count
, clear_rects
,
6354 wine_dbgstr_rect(draw_rect
), flags
, debug_color(colour
), depth
, stencil
);
6359 clear_rects
= draw_rect
;
6362 if (flags
& WINED3DCLEAR_TARGET
)
6364 for (i
= 0; i
< rt_count
; ++i
)
6366 if (!(view
= fb
->render_targets
[i
]))
6369 if (blitter_use_cpu_clear(view
))
6371 next_flags
|= WINED3DCLEAR_TARGET
;
6372 flags
&= ~WINED3DCLEAR_TARGET
;
6373 next_rt_count
= rt_count
;
6380 if ((flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)) && (view
= fb
->depth_stencil
)
6381 && (!view
->format
->depth_size
|| (flags
& WINED3DCLEAR_ZBUFFER
))
6382 && (!view
->format
->stencil_size
|| (flags
& WINED3DCLEAR_STENCIL
))
6383 && blitter_use_cpu_clear(view
))
6385 next_flags
|= flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
6386 flags
&= ~(WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
6391 context_vk
= wined3d_context_vk(context_acquire(&device_vk
->d
, NULL
, 0));
6393 for (i
= 0; i
< rt_count
; ++i
)
6395 if (!(view
= fb
->render_targets
[i
]))
6398 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
6399 have_identical_size
= false;
6402 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
6404 view
= fb
->depth_stencil
;
6406 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
6407 have_identical_size
= false;
6410 if (have_identical_size
)
6412 vk_blitter_clear_rendertargets(context_vk
, rt_count
, fb
, rect_count
,
6413 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
6417 for (i
= 0; i
< rt_count
; ++i
)
6419 if (!(view
= fb
->render_targets
[i
]))
6422 tmp_fb
.render_targets
[0] = view
;
6423 tmp_fb
.depth_stencil
= NULL
;
6424 vk_blitter_clear_rendertargets(context_vk
, 1, &tmp_fb
, rect_count
,
6425 clear_rects
, draw_rect
, WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
6427 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
6429 tmp_fb
.render_targets
[0] = NULL
;
6430 tmp_fb
.depth_stencil
= fb
->depth_stencil
;
6431 vk_blitter_clear_rendertargets(context_vk
, 0, &tmp_fb
, rect_count
,
6432 clear_rects
, draw_rect
, flags
& ~WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
6436 context_release(&context_vk
->c
);
6442 if (!(next
= blitter
->next
))
6444 ERR("No blitter to handle clear.\n");
6448 TRACE("Forwarding to blitter %p.\n", next
);
6449 next
->ops
->blitter_clear(next
, device
, next_rt_count
, fb
, rect_count
,
6450 clear_rects
, draw_rect
, next_flags
, colour
, depth
, stencil
);
6453 static bool vk_blitter_blit_supported(enum wined3d_blit_op op
, const struct wined3d_context
*context
,
6454 const struct wined3d_resource
*src_resource
, const RECT
*src_rect
,
6455 const struct wined3d_resource
*dst_resource
, const RECT
*dst_rect
, const struct wined3d_format
*resolve_format
)
6457 const struct wined3d_format
*src_format
= src_resource
->format
;
6458 const struct wined3d_format
*dst_format
= dst_resource
->format
;
6460 if (!(dst_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
6462 TRACE("Destination resource does not have GPU access.\n");
6466 if (!(src_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
6468 TRACE("Source resource does not have GPU access.\n");
6472 if (dst_format
->id
!= src_format
->id
)
6474 if (!is_identity_fixup(dst_format
->color_fixup
))
6476 TRACE("Destination fixups are not supported.\n");
6480 if (!is_identity_fixup(src_format
->color_fixup
))
6482 TRACE("Source fixups are not supported.\n");
6486 if (op
!= WINED3D_BLIT_OP_RAW_BLIT
6487 && wined3d_format_vk(src_format
)->vk_format
!= wined3d_format_vk(dst_format
)->vk_format
6488 && ((!wined3d_format_is_typeless(src_format
) && !wined3d_format_is_typeless(dst_format
))
6489 || !resolve_format
))
6491 TRACE("Format conversion not supported.\n");
6496 if (wined3d_resource_get_sample_count(dst_resource
) > 1)
6498 TRACE("Multi-sample destination resource not supported.\n");
6502 if (op
== WINED3D_BLIT_OP_RAW_BLIT
)
6505 if (op
!= WINED3D_BLIT_OP_COLOR_BLIT
)
6507 TRACE("Unsupported blit operation %#x.\n", op
);
6511 if ((src_rect
->right
- src_rect
->left
!= dst_rect
->right
- dst_rect
->left
)
6512 || (src_rect
->bottom
- src_rect
->top
!= dst_rect
->bottom
- dst_rect
->top
))
6514 TRACE("Scaling not supported.\n");
6521 static DWORD
vk_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
6522 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
6523 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
6524 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
6525 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
6526 const struct wined3d_format
*resolve_format
)
6528 struct wined3d_texture_vk
*src_texture_vk
= wined3d_texture_vk(src_texture
);
6529 struct wined3d_texture_vk
*dst_texture_vk
= wined3d_texture_vk(dst_texture
);
6530 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
6531 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
6532 VkImageSubresourceRange vk_src_range
, vk_dst_range
;
6533 VkCommandBuffer vk_command_buffer
;
6534 struct wined3d_blitter
*next
;
6535 unsigned src_sample_count
;
6536 bool resolve
= false;
6538 TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, "
6539 "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, "
6540 "colour_key %p, filter %s, resolve format %p.\n",
6541 blitter
, op
, context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
6542 wine_dbgstr_rect(src_rect
), dst_texture
, dst_sub_resource_idx
, wined3d_debug_location(dst_location
),
6543 wine_dbgstr_rect(dst_rect
), colour_key
, debug_d3dtexturefiltertype(filter
), resolve_format
);
6545 if (!vk_blitter_blit_supported(op
, context
, &src_texture
->resource
, src_rect
, &dst_texture
->resource
, dst_rect
,
6549 src_sample_count
= wined3d_resource_get_sample_count(&src_texture_vk
->t
.resource
);
6550 if (src_sample_count
> 1)
6553 vk_src_range
.aspectMask
= vk_aspect_mask_from_format(src_texture_vk
->t
.resource
.format
);
6554 vk_src_range
.baseMipLevel
= src_sub_resource_idx
% src_texture
->level_count
;
6555 vk_src_range
.levelCount
= 1;
6556 vk_src_range
.baseArrayLayer
= src_sub_resource_idx
/ src_texture
->level_count
;
6557 vk_src_range
.layerCount
= 1;
6559 vk_dst_range
.aspectMask
= vk_aspect_mask_from_format(dst_texture_vk
->t
.resource
.format
);
6560 vk_dst_range
.baseMipLevel
= dst_sub_resource_idx
% dst_texture
->level_count
;
6561 vk_dst_range
.levelCount
= 1;
6562 vk_dst_range
.baseArrayLayer
= dst_sub_resource_idx
/ dst_texture
->level_count
;
6563 vk_dst_range
.layerCount
= 1;
6565 if (!wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6566 ERR("Failed to load the source sub-resource.\n");
6568 if (wined3d_texture_is_full_rect(dst_texture
, vk_dst_range
.baseMipLevel
, dst_rect
))
6570 if (!wined3d_texture_prepare_location(dst_texture
,
6571 dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6573 ERR("Failed to prepare the destination sub-resource.\n");
6579 if (!wined3d_texture_load_location(dst_texture
,
6580 dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6582 ERR("Failed to load the destination sub-resource.\n");
6587 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
6589 ERR("Failed to get command buffer.\n");
6593 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6594 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6595 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6596 VK_ACCESS_TRANSFER_READ_BIT
,
6597 src_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6598 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6599 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6600 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6601 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6602 VK_ACCESS_TRANSFER_WRITE_BIT
,
6603 dst_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
6604 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6608 const struct wined3d_format_vk
*src_format_vk
= wined3d_format_vk(src_texture
->resource
.format
);
6609 const struct wined3d_format_vk
*dst_format_vk
= wined3d_format_vk(dst_texture
->resource
.format
);
6610 const unsigned int usage
= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
6611 | VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
6612 VkImage src_vk_image
, dst_vk_image
;
6613 VkImageSubresourceRange vk_range
;
6614 VkImageResolve resolve_region
;
6615 VkImageType vk_image_type
;
6616 VkImageCopy copy_region
;
6621 vk_format
= wined3d_format_vk(resolve_format
)->vk_format
;
6623 else if (!wined3d_format_is_typeless(src_texture
->resource
.format
))
6625 vk_format
= src_format_vk
->vk_format
;
6629 vk_format
= dst_format_vk
->vk_format
;
6632 switch (src_texture
->resource
.type
)
6634 case WINED3D_RTYPE_TEXTURE_1D
:
6635 vk_image_type
= VK_IMAGE_TYPE_1D
;
6637 case WINED3D_RTYPE_TEXTURE_2D
:
6638 vk_image_type
= VK_IMAGE_TYPE_2D
;
6640 case WINED3D_RTYPE_TEXTURE_3D
:
6641 vk_image_type
= VK_IMAGE_TYPE_3D
;
6644 ERR("Unexpected resource type: %s\n", debug_d3dresourcetype(src_texture
->resource
.type
));
6648 vk_range
.baseMipLevel
= 0;
6649 vk_range
.levelCount
= 1;
6650 vk_range
.baseArrayLayer
= 0;
6651 vk_range
.layerCount
= 1;
6653 resolve_region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6654 resolve_region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6655 resolve_region
.extent
.width
= src_rect
->right
- src_rect
->left
;
6656 resolve_region
.extent
.height
= src_rect
->bottom
- src_rect
->top
;
6657 resolve_region
.extent
.depth
= 1;
6659 /* In case of typeless resolve the texture type may not match the resolve type.
6660 * To handle that, allocate intermediate texture(s) to resolve from/to.
6661 * A possible performance improvement would be to resolve using a shader instead. */
6662 if (src_format_vk
->vk_format
!= vk_format
)
6664 struct wined3d_image_vk src_image
;
6666 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, usage
, vk_format
,
6667 resolve_region
.extent
.width
, resolve_region
.extent
.height
, 1,
6668 src_sample_count
, 1, 1, 0, &src_image
))
6671 wined3d_context_vk_reference_image(context_vk
, &src_image
);
6672 src_vk_image
= src_image
.vk_image
;
6673 wined3d_context_vk_destroy_image(context_vk
, &src_image
);
6675 vk_range
.aspectMask
= vk_src_range
.aspectMask
;
6677 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6678 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6679 0, VK_ACCESS_TRANSFER_WRITE_BIT
, VK_IMAGE_LAYOUT_UNDEFINED
,
6680 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, src_vk_image
, &vk_range
);
6682 copy_region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6683 copy_region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6684 copy_region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6685 copy_region
.srcSubresource
.layerCount
= 1;
6686 copy_region
.srcOffset
.x
= src_rect
->left
;
6687 copy_region
.srcOffset
.y
= src_rect
->top
;
6688 copy_region
.srcOffset
.z
= 0;
6689 copy_region
.dstSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6690 copy_region
.dstSubresource
.mipLevel
= 0;
6691 copy_region
.dstSubresource
.baseArrayLayer
= 0;
6692 copy_region
.dstSubresource
.layerCount
= 1;
6693 copy_region
.dstOffset
.x
= 0;
6694 copy_region
.dstOffset
.y
= 0;
6695 copy_region
.dstOffset
.z
= 0;
6696 copy_region
.extent
.width
= resolve_region
.extent
.width
;
6697 copy_region
.extent
.height
= resolve_region
.extent
.height
;
6698 copy_region
.extent
.depth
= 1;
6700 VK_CALL(vkCmdCopyImage(vk_command_buffer
, src_texture_vk
->image
.vk_image
,
6701 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
6704 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6705 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6706 VK_ACCESS_TRANSFER_WRITE_BIT
, VK_ACCESS_TRANSFER_READ_BIT
,
6707 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6708 src_vk_image
, &vk_range
);
6710 resolve_region
.srcSubresource
.mipLevel
= 0;
6711 resolve_region
.srcSubresource
.baseArrayLayer
= 0;
6712 resolve_region
.srcSubresource
.layerCount
= 1;
6713 resolve_region
.srcOffset
.x
= 0;
6714 resolve_region
.srcOffset
.y
= 0;
6715 resolve_region
.srcOffset
.z
= 0;
6719 src_vk_image
= src_texture_vk
->image
.vk_image
;
6721 resolve_region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6722 resolve_region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6723 resolve_region
.srcSubresource
.layerCount
= 1;
6724 resolve_region
.srcOffset
.x
= src_rect
->left
;
6725 resolve_region
.srcOffset
.y
= src_rect
->top
;
6726 resolve_region
.srcOffset
.z
= 0;
6729 if (dst_format_vk
->vk_format
!= vk_format
)
6731 struct wined3d_image_vk dst_image
;
6733 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, usage
, vk_format
,
6734 resolve_region
.extent
.width
, resolve_region
.extent
.height
, 1,
6735 VK_SAMPLE_COUNT_1_BIT
, 1, 1, 0, &dst_image
))
6738 wined3d_context_vk_reference_image(context_vk
, &dst_image
);
6739 dst_vk_image
= dst_image
.vk_image
;
6740 wined3d_context_vk_destroy_image(context_vk
, &dst_image
);
6742 vk_range
.aspectMask
= vk_dst_range
.aspectMask
;
6743 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6744 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
, 0, VK_ACCESS_TRANSFER_WRITE_BIT
,
6745 VK_IMAGE_LAYOUT_UNDEFINED
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_vk_image
, &vk_range
);
6747 resolve_region
.dstSubresource
.mipLevel
= 0;
6748 resolve_region
.dstSubresource
.baseArrayLayer
= 0;
6749 resolve_region
.dstSubresource
.layerCount
= 1;
6750 resolve_region
.dstOffset
.x
= 0;
6751 resolve_region
.dstOffset
.y
= 0;
6752 resolve_region
.dstOffset
.z
= 0;
6756 dst_vk_image
= dst_texture_vk
->image
.vk_image
;
6758 resolve_region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6759 resolve_region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6760 resolve_region
.dstSubresource
.layerCount
= 1;
6761 resolve_region
.dstOffset
.x
= dst_rect
->left
;
6762 resolve_region
.dstOffset
.y
= dst_rect
->top
;
6763 resolve_region
.dstOffset
.z
= 0;
6766 VK_CALL(vkCmdResolveImage(vk_command_buffer
, src_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6767 dst_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, &resolve_region
));
6769 if (dst_vk_image
!= dst_texture_vk
->image
.vk_image
)
6771 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6772 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6773 VK_ACCESS_TRANSFER_WRITE_BIT
, VK_ACCESS_TRANSFER_READ_BIT
,
6774 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6775 dst_vk_image
, &vk_range
);
6777 copy_region
.srcSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6778 copy_region
.srcSubresource
.mipLevel
= 0;
6779 copy_region
.srcSubresource
.baseArrayLayer
= 0;
6780 copy_region
.srcSubresource
.layerCount
= 1;
6781 copy_region
.srcOffset
.x
= 0;
6782 copy_region
.srcOffset
.y
= 0;
6783 copy_region
.srcOffset
.z
= 0;
6784 copy_region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6785 copy_region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6786 copy_region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6787 copy_region
.dstSubresource
.layerCount
= 1;
6788 copy_region
.dstOffset
.x
= dst_rect
->left
;
6789 copy_region
.dstOffset
.y
= dst_rect
->top
;
6790 copy_region
.dstOffset
.z
= 0;
6791 copy_region
.extent
.width
= resolve_region
.extent
.width
;
6792 copy_region
.extent
.height
= resolve_region
.extent
.height
;
6793 copy_region
.extent
.depth
= 1;
6795 VK_CALL(vkCmdCopyImage(vk_command_buffer
, dst_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6796 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ©_region
));
6803 region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6804 region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6805 region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6806 region
.srcSubresource
.layerCount
= vk_src_range
.layerCount
;
6807 region
.srcOffset
.x
= src_rect
->left
;
6808 region
.srcOffset
.y
= src_rect
->top
;
6809 region
.srcOffset
.z
= 0;
6810 region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6811 region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6812 region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6813 region
.dstSubresource
.layerCount
= vk_dst_range
.layerCount
;
6814 region
.dstOffset
.x
= dst_rect
->left
;
6815 region
.dstOffset
.y
= dst_rect
->top
;
6816 region
.dstOffset
.z
= 0;
6817 region
.extent
.width
= src_rect
->right
- src_rect
->left
;
6818 region
.extent
.height
= src_rect
->bottom
- src_rect
->top
;
6819 region
.extent
.depth
= 1;
6821 VK_CALL(vkCmdCopyImage(vk_command_buffer
, src_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6822 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ®ion
));
6825 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6826 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6827 VK_ACCESS_TRANSFER_WRITE_BIT
,
6828 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6829 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
6830 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6831 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6832 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6833 VK_ACCESS_TRANSFER_READ_BIT
,
6834 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6835 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
6836 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6838 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
6839 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
6840 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
))
6841 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location
));
6843 wined3d_context_vk_reference_texture(context_vk
, src_texture_vk
);
6844 wined3d_context_vk_reference_texture(context_vk
, dst_texture_vk
);
6846 return dst_location
| WINED3D_LOCATION_TEXTURE_RGB
;
6849 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6850 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6851 VK_ACCESS_TRANSFER_WRITE_BIT
,
6852 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6853 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
6854 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6855 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6856 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6857 VK_ACCESS_TRANSFER_READ_BIT
,
6858 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6859 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
6860 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6863 if (!(next
= blitter
->next
))
6865 ERR("No blitter to handle blit op %#x.\n", op
);
6866 return dst_location
;
6869 TRACE("Forwarding to blitter %p.\n", next
);
6870 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6871 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
, resolve_format
);
6874 static const struct wined3d_blitter_ops vk_blitter_ops
=
6876 .blitter_destroy
= vk_blitter_destroy
,
6877 .blitter_clear
= vk_blitter_clear
,
6878 .blitter_blit
= vk_blitter_blit
,
6881 void wined3d_vk_blitter_create(struct wined3d_blitter
**next
)
6883 struct wined3d_blitter
*blitter
;
6885 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6888 TRACE("Created blitter %p.\n", blitter
);
6890 blitter
->ops
= &vk_blitter_ops
;
6891 blitter
->next
= *next
;