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.");
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.");
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 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 /* Conditinal 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 HRESULT
wined3d_texture_check_box_dimensions(const struct wined3d_texture
*texture
,
1657 unsigned int level
, const struct wined3d_box
*box
)
1659 const struct wined3d_format
*format
= texture
->resource
.format
;
1660 unsigned int width_mask
, height_mask
, width
, height
, depth
;
1662 width
= wined3d_texture_get_level_width(texture
, level
);
1663 height
= wined3d_texture_get_level_height(texture
, level
);
1664 depth
= wined3d_texture_get_level_depth(texture
, level
);
1666 if (box
->left
>= box
->right
|| box
->right
> width
1667 || box
->top
>= box
->bottom
|| box
->bottom
> height
1668 || box
->front
>= box
->back
|| box
->back
> depth
)
1670 WARN("Box %s is invalid.\n", debug_box(box
));
1671 return WINEDDERR_INVALIDRECT
;
1674 if (texture
->resource
.format_flags
& WINED3DFMT_FLAG_BLOCKS
)
1676 /* This assumes power of two block sizes, but NPOT block sizes would
1679 * This also assumes that the format's block depth is 1. */
1680 width_mask
= format
->block_width
- 1;
1681 height_mask
= format
->block_height
- 1;
1683 if ((box
->left
& width_mask
) || (box
->top
& height_mask
)
1684 || (box
->right
& width_mask
&& box
->right
!= width
)
1685 || (box
->bottom
& height_mask
&& box
->bottom
!= height
))
1687 WARN("Box %s is misaligned for %ux%u blocks.\n",
1688 debug_box(box
), format
->block_width
, format
->block_height
);
1689 return WINED3DERR_INVALIDCALL
;
1696 void CDECL
wined3d_texture_get_pitch(const struct wined3d_texture
*texture
,
1697 unsigned int level
, unsigned int *row_pitch
, unsigned int *slice_pitch
)
1699 const struct wined3d_resource
*resource
= &texture
->resource
;
1700 unsigned int width
= wined3d_texture_get_level_width(texture
, level
);
1701 unsigned int height
= wined3d_texture_get_level_height(texture
, level
);
1703 if (texture
->row_pitch
)
1705 *row_pitch
= texture
->row_pitch
;
1706 *slice_pitch
= texture
->slice_pitch
;
1710 wined3d_format_calculate_pitch(resource
->format
, resource
->device
->surface_alignment
,
1711 width
, height
, row_pitch
, slice_pitch
);
1714 DWORD CDECL
wined3d_texture_set_lod(struct wined3d_texture
*texture
, DWORD lod
)
1716 struct wined3d_resource
*resource
;
1717 DWORD old
= texture
->lod
;
1719 TRACE("texture %p, lod %u.\n", texture
, lod
);
1721 /* The d3d9:texture test shows that SetLOD is ignored on non-managed
1722 * textures. The call always returns 0, and GetLOD always returns 0. */
1723 resource
= &texture
->resource
;
1724 if (!wined3d_resource_access_is_managed(resource
->access
))
1726 TRACE("Ignoring LOD on texture with resource access %s.\n",
1727 wined3d_debug_resource_access(resource
->access
));
1731 if (lod
>= texture
->level_count
)
1732 lod
= texture
->level_count
- 1;
1734 if (texture
->lod
!= lod
)
1736 struct wined3d_device
*device
= resource
->device
;
1738 wined3d_resource_wait_idle(resource
);
1741 wined3d_texture_gl(texture
)->texture_rgb
.base_level
= ~0u;
1742 wined3d_texture_gl(texture
)->texture_srgb
.base_level
= ~0u;
1743 if (resource
->bind_count
)
1744 wined3d_cs_emit_set_sampler_state(device
->cs
, texture
->sampler
, WINED3D_SAMP_MAX_MIP_LEVEL
,
1745 device
->cs
->c
.state
->sampler_states
[texture
->sampler
][WINED3D_SAMP_MAX_MIP_LEVEL
]);
1751 DWORD CDECL
wined3d_texture_get_lod(const struct wined3d_texture
*texture
)
1753 TRACE("texture %p, returning %u.\n", texture
, texture
->lod
);
1755 return texture
->lod
;
1758 DWORD CDECL
wined3d_texture_get_level_count(const struct wined3d_texture
*texture
)
1760 TRACE("texture %p, returning %u.\n", texture
, texture
->level_count
);
1762 return texture
->level_count
;
1765 HRESULT CDECL
wined3d_texture_set_color_key(struct wined3d_texture
*texture
,
1766 DWORD flags
, const struct wined3d_color_key
*color_key
)
1768 struct wined3d_device
*device
= texture
->resource
.device
;
1769 static const DWORD all_flags
= WINED3D_CKEY_DST_BLT
| WINED3D_CKEY_DST_OVERLAY
1770 | WINED3D_CKEY_SRC_BLT
| WINED3D_CKEY_SRC_OVERLAY
;
1772 TRACE("texture %p, flags %#x, color_key %p.\n", texture
, flags
, color_key
);
1774 if (flags
& ~all_flags
)
1776 WARN("Invalid flags passed, returning WINED3DERR_INVALIDCALL.\n");
1777 return WINED3DERR_INVALIDCALL
;
1780 wined3d_cs_emit_set_color_key(device
->cs
, texture
, flags
, color_key
);
1785 /* In D3D the depth stencil dimensions have to be greater than or equal to the
1786 * render target dimensions. With FBOs, the dimensions have to be an exact match. */
1787 /* TODO: We should synchronize the renderbuffer's content with the texture's content. */
1788 /* Context activation is done by the caller. */
1789 void wined3d_texture_gl_set_compatible_renderbuffer(struct wined3d_texture_gl
*texture_gl
,
1790 struct wined3d_context_gl
*context_gl
, unsigned int level
, const struct wined3d_rendertarget_info
*rt
)
1792 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
1793 struct wined3d_renderbuffer_entry
*entry
;
1794 unsigned int src_width
, src_height
;
1795 unsigned int width
, height
;
1796 GLuint renderbuffer
= 0;
1798 if (gl_info
->supported
[ARB_FRAMEBUFFER_OBJECT
])
1801 if (rt
&& rt
->resource
->format
->id
!= WINED3DFMT_NULL
)
1803 struct wined3d_texture
*rt_texture
;
1804 unsigned int rt_level
;
1806 if (rt
->resource
->type
== WINED3D_RTYPE_BUFFER
)
1808 FIXME("Unsupported resource type %s.\n", debug_d3dresourcetype(rt
->resource
->type
));
1811 rt_texture
= wined3d_texture_from_resource(rt
->resource
);
1812 rt_level
= rt
->sub_resource_idx
% rt_texture
->level_count
;
1814 width
= wined3d_texture_get_level_pow2_width(rt_texture
, rt_level
);
1815 height
= wined3d_texture_get_level_pow2_height(rt_texture
, rt_level
);
1819 width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
1820 height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
1823 src_width
= wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
);
1824 src_height
= wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
);
1826 /* A depth stencil smaller than the render target is not valid */
1827 if (width
> src_width
|| height
> src_height
)
1830 /* Remove any renderbuffer set if the sizes match */
1831 if (width
== src_width
&& height
== src_height
)
1833 texture_gl
->current_renderbuffer
= NULL
;
1837 /* Look if we've already got a renderbuffer of the correct dimensions */
1838 LIST_FOR_EACH_ENTRY(entry
, &texture_gl
->renderbuffers
, struct wined3d_renderbuffer_entry
, entry
)
1840 if (entry
->width
== width
&& entry
->height
== height
)
1842 renderbuffer
= entry
->id
;
1843 texture_gl
->current_renderbuffer
= entry
;
1850 const struct wined3d_format_gl
*format_gl
;
1852 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
1853 gl_info
->fbo_ops
.glGenRenderbuffers(1, &renderbuffer
);
1854 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, renderbuffer
);
1855 gl_info
->fbo_ops
.glRenderbufferStorage(GL_RENDERBUFFER
, format_gl
->internal
, width
, height
);
1857 entry
= heap_alloc(sizeof(*entry
));
1858 entry
->width
= width
;
1859 entry
->height
= height
;
1860 entry
->id
= renderbuffer
;
1861 list_add_head(&texture_gl
->renderbuffers
, &entry
->entry
);
1863 texture_gl
->current_renderbuffer
= entry
;
1866 checkGLcall("set compatible renderbuffer");
1869 HRESULT CDECL
wined3d_texture_update_desc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
1870 UINT width
, UINT height
, enum wined3d_format_id format_id
,
1871 enum wined3d_multisample_type multisample_type
, UINT multisample_quality
, void *mem
, UINT pitch
)
1873 struct wined3d_texture_sub_resource
*sub_resource
;
1874 unsigned int i
, level
, sub_resource_count
;
1875 const struct wined3d_d3d_info
*d3d_info
;
1876 const struct wined3d_gl_info
*gl_info
;
1877 const struct wined3d_format
*format
;
1878 struct wined3d_device
*device
;
1879 unsigned int resource_size
;
1880 const struct wined3d
*d3d
;
1881 unsigned int slice_pitch
;
1882 bool update_memory_only
;
1883 bool create_dib
= false;
1885 TRACE("texture %p, width %u, height %u, format %s, multisample_type %#x, multisample_quality %u, "
1886 "mem %p, pitch %u, sub_resource_idx %u.\n",
1887 texture
, width
, height
, debug_d3dformat(format_id
), multisample_type
, multisample_quality
, mem
, pitch
,
1890 device
= texture
->resource
.device
;
1891 d3d
= device
->wined3d
;
1892 gl_info
= &device
->adapter
->gl_info
;
1893 d3d_info
= &device
->adapter
->d3d_info
;
1894 format
= wined3d_get_format(device
->adapter
, format_id
, texture
->resource
.bind_flags
);
1895 resource_size
= wined3d_format_calculate_size(format
, device
->surface_alignment
, width
, height
, 1);
1896 level
= sub_resource_idx
% texture
->level_count
;
1897 sub_resource_count
= texture
->level_count
* texture
->layer_count
;
1899 update_memory_only
= width
== wined3d_texture_get_level_width(texture
, level
)
1900 && height
== wined3d_texture_get_level_height(texture
, level
)
1901 && format_id
== texture
->resource
.format
->id
&& multisample_type
== texture
->resource
.multisample_type
1902 && multisample_quality
== texture
->resource
.multisample_quality
;
1905 slice_pitch
= height
* pitch
;
1907 wined3d_format_calculate_pitch(format
, 1, width
, height
, &pitch
, &slice_pitch
);
1909 if (update_memory_only
)
1911 unsigned int current_row_pitch
, current_slice_pitch
;
1913 wined3d_texture_get_pitch(texture
, level
, ¤t_row_pitch
, ¤t_slice_pitch
);
1914 update_memory_only
= pitch
== current_row_pitch
&& slice_pitch
== current_slice_pitch
;
1918 return WINED3DERR_INVALIDCALL
;
1920 if (sub_resource_count
> 1 && !update_memory_only
)
1922 FIXME("Texture has multiple sub-resources, not supported.\n");
1923 return WINED3DERR_INVALIDCALL
;
1926 if (texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
1928 WARN("Not supported on %s.\n", debug_d3dresourcetype(texture
->resource
.type
));
1929 return WINED3DERR_INVALIDCALL
;
1932 if (texture
->resource
.map_count
)
1934 WARN("Texture is mapped.\n");
1935 return WINED3DERR_INVALIDCALL
;
1938 /* We have no way of supporting a pitch that is not a multiple of the pixel
1939 * byte width short of uploading the texture row-by-row.
1940 * Fortunately that's not an issue since D3D9Ex doesn't allow a custom pitch
1941 * for user-memory textures (it always expects packed data) while DirectDraw
1942 * requires a 4-byte aligned pitch and doesn't support texture formats
1943 * larger than 4 bytes per pixel nor any format using 3 bytes per pixel.
1944 * This check is here to verify that the assumption holds. */
1945 if (pitch
% texture
->resource
.format
->byte_count
)
1947 WARN("Pitch unsupported, not a multiple of the texture format byte width.\n");
1948 return WINED3DERR_INVALIDCALL
;
1951 if (device
->d3d_initialized
)
1952 wined3d_cs_emit_unload_resource(device
->cs
, &texture
->resource
);
1953 wined3d_resource_wait_idle(&texture
->resource
);
1955 if (texture
->dc_info
&& texture
->dc_info
[0].dc
)
1957 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
1959 wined3d_cs_destroy_object(device
->cs
, wined3d_texture_destroy_dc
, &texture_idx
);
1960 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
1964 texture
->sub_resources
[sub_resource_idx
].user_memory
= mem
;
1966 if (update_memory_only
)
1968 for (i
= 0; i
< sub_resource_count
; ++i
)
1969 if (!texture
->sub_resources
[i
].user_memory
)
1972 if (i
== sub_resource_count
)
1973 wined3d_resource_free_sysmem(&texture
->resource
);
1977 wined3d_resource_free_sysmem(&texture
->resource
);
1979 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
1981 texture
->row_pitch
= pitch
;
1982 texture
->slice_pitch
= slice_pitch
;
1984 texture
->resource
.format
= format
;
1985 texture
->resource
.multisample_type
= multisample_type
;
1986 texture
->resource
.multisample_quality
= multisample_quality
;
1987 texture
->resource
.width
= width
;
1988 texture
->resource
.height
= height
;
1989 if (!(texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_CPU
) && d3d
->flags
& WINED3D_VIDMEM_ACCOUNTING
)
1990 adapter_adjust_memory(device
->adapter
, (INT64
)texture
->slice_pitch
- texture
->resource
.size
);
1991 texture
->resource
.size
= texture
->slice_pitch
;
1992 sub_resource
->size
= texture
->slice_pitch
;
1993 sub_resource
->locations
= WINED3D_LOCATION_DISCARDED
;
1995 if (texture
->texture_ops
== &texture_gl_ops
)
1997 if (multisample_type
&& gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
1999 wined3d_texture_gl(texture
)->target
= GL_TEXTURE_2D_MULTISAMPLE
;
2000 texture
->flags
&= ~WINED3D_TEXTURE_DOWNLOADABLE
;
2004 wined3d_texture_gl(texture
)->target
= GL_TEXTURE_2D
;
2005 texture
->flags
|= WINED3D_TEXTURE_DOWNLOADABLE
;
2009 if (((width
& (width
- 1)) || (height
& (height
- 1))) && !d3d_info
->texture_npot
2010 && !d3d_info
->texture_npot_conditional
)
2012 texture
->flags
|= WINED3D_TEXTURE_COND_NP2_EMULATED
;
2013 texture
->pow2_width
= texture
->pow2_height
= 1;
2014 while (texture
->pow2_width
< width
)
2015 texture
->pow2_width
<<= 1;
2016 while (texture
->pow2_height
< height
)
2017 texture
->pow2_height
<<= 1;
2021 texture
->flags
&= ~WINED3D_TEXTURE_COND_NP2_EMULATED
;
2022 texture
->pow2_width
= width
;
2023 texture
->pow2_height
= height
;
2027 if (!mem
&& !wined3d_resource_prepare_sysmem(&texture
->resource
))
2028 ERR("Failed to allocate resource memory.\n");
2030 /* The format might be changed to a format that needs conversion.
2031 * If the surface didn't use PBOs previously but could now, don't
2032 * change it - whatever made us not use PBOs might come back, e.g.
2034 if (texture
->resource
.map_binding
== WINED3D_LOCATION_BUFFER
&& !wined3d_texture_use_pbo(texture
, gl_info
))
2035 texture
->resource
.map_binding
= WINED3D_LOCATION_SYSMEM
;
2037 wined3d_texture_validate_location(texture
, sub_resource_idx
, WINED3D_LOCATION_SYSMEM
);
2038 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~WINED3D_LOCATION_SYSMEM
);
2042 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
2044 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
2045 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
2051 /* Context activation is done by the caller. */
2052 static void wined3d_texture_gl_prepare_buffer_object(struct wined3d_texture_gl
*texture_gl
,
2053 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
)
2055 struct wined3d_texture_sub_resource
*sub_resource
;
2056 struct wined3d_bo_gl
*bo
;
2058 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
2059 bo
= &sub_resource
->bo
;
2063 if (!wined3d_context_gl_create_bo(context_gl
, sub_resource
->size
, GL_PIXEL_UNPACK_BUFFER
,
2064 GL_STREAM_DRAW
, true, GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
| GL_CLIENT_STORAGE_BIT
, bo
))
2067 TRACE("Created buffer object %u for texture %p, sub-resource %u.\n", bo
->id
, texture_gl
, sub_resource_idx
);
2070 static void wined3d_texture_force_reload(struct wined3d_texture
*texture
)
2072 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
2075 texture
->flags
&= ~(WINED3D_TEXTURE_RGB_ALLOCATED
| WINED3D_TEXTURE_SRGB_ALLOCATED
2076 | WINED3D_TEXTURE_CONVERTED
);
2077 texture
->async
.flags
&= ~WINED3D_TEXTURE_ASYNC_COLOR_KEY
;
2078 for (i
= 0; i
< sub_count
; ++i
)
2080 wined3d_texture_invalidate_location(texture
, i
,
2081 WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
2085 /* Context activation is done by the caller. */
2086 void wined3d_texture_gl_prepare_texture(struct wined3d_texture_gl
*texture_gl
,
2087 struct wined3d_context_gl
*context_gl
, BOOL srgb
)
2089 DWORD alloc_flag
= srgb
? WINED3D_TEXTURE_SRGB_ALLOCATED
: WINED3D_TEXTURE_RGB_ALLOCATED
;
2090 const struct wined3d_d3d_info
*d3d_info
= context_gl
->c
.d3d_info
;
2091 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2092 struct wined3d_resource
*resource
= &texture_gl
->t
.resource
;
2093 const struct wined3d_device
*device
= resource
->device
;
2094 const struct wined3d_format
*format
= resource
->format
;
2095 const struct wined3d_color_key_conversion
*conversion
;
2096 const struct wined3d_format_gl
*format_gl
;
2099 TRACE("texture_gl %p, context_gl %p, format %s.\n", texture_gl
, context_gl
, debug_d3dformat(format
->id
));
2101 if (!d3d_info
->shader_color_key
2102 && !(texture_gl
->t
.async
.flags
& WINED3D_TEXTURE_ASYNC_COLOR_KEY
)
2103 != !(texture_gl
->t
.async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
))
2105 wined3d_texture_force_reload(&texture_gl
->t
);
2107 if (texture_gl
->t
.async
.color_key_flags
& WINED3D_CKEY_SRC_BLT
)
2108 texture_gl
->t
.async
.flags
|= WINED3D_TEXTURE_ASYNC_COLOR_KEY
;
2111 if (texture_gl
->t
.flags
& alloc_flag
)
2114 if (resource
->format_flags
& WINED3DFMT_FLAG_DECOMPRESS
)
2116 TRACE("WINED3DFMT_FLAG_DECOMPRESS set.\n");
2117 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2118 format
= wined3d_resource_get_decompress_format(resource
);
2120 else if (format
->conv_byte_count
)
2122 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2124 else if ((conversion
= wined3d_format_get_color_key_conversion(&texture_gl
->t
, TRUE
)))
2126 texture_gl
->t
.flags
|= WINED3D_TEXTURE_CONVERTED
;
2127 format
= wined3d_get_format(device
->adapter
, conversion
->dst_format
, resource
->bind_flags
);
2128 TRACE("Using format %s for color key conversion.\n", debug_d3dformat(format
->id
));
2130 format_gl
= wined3d_format_gl(format
);
2132 wined3d_texture_gl_bind_and_dirtify(texture_gl
, context_gl
, srgb
);
2134 internal
= wined3d_gl_get_internal_format(resource
, format_gl
, srgb
);
2136 FIXME("No GL internal format for format %s.\n", debug_d3dformat(format
->id
));
2138 TRACE("internal %#x, format %#x, type %#x.\n", internal
, format_gl
->format
, format_gl
->type
);
2140 if (wined3d_texture_use_immutable_storage(&texture_gl
->t
, gl_info
))
2141 wined3d_texture_gl_allocate_immutable_storage(texture_gl
, internal
, gl_info
);
2143 wined3d_texture_gl_allocate_mutable_storage(texture_gl
, internal
, format_gl
, gl_info
);
2144 texture_gl
->t
.flags
|= alloc_flag
;
2147 static void wined3d_texture_gl_prepare_rb(struct wined3d_texture_gl
*texture_gl
,
2148 const struct wined3d_gl_info
*gl_info
, BOOL multisample
)
2150 const struct wined3d_format_gl
*format_gl
;
2152 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
2157 if (texture_gl
->rb_multisample
)
2160 samples
= wined3d_resource_get_sample_count(&texture_gl
->t
.resource
);
2162 gl_info
->fbo_ops
.glGenRenderbuffers(1, &texture_gl
->rb_multisample
);
2163 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, texture_gl
->rb_multisample
);
2164 gl_info
->fbo_ops
.glRenderbufferStorageMultisample(GL_RENDERBUFFER
, samples
,
2165 format_gl
->internal
, texture_gl
->t
.resource
.width
, texture_gl
->t
.resource
.height
);
2166 checkGLcall("glRenderbufferStorageMultisample()");
2167 TRACE("Created multisample rb %u.\n", texture_gl
->rb_multisample
);
2171 if (texture_gl
->rb_resolved
)
2174 gl_info
->fbo_ops
.glGenRenderbuffers(1, &texture_gl
->rb_resolved
);
2175 gl_info
->fbo_ops
.glBindRenderbuffer(GL_RENDERBUFFER
, texture_gl
->rb_resolved
);
2176 gl_info
->fbo_ops
.glRenderbufferStorage(GL_RENDERBUFFER
, format_gl
->internal
,
2177 texture_gl
->t
.resource
.width
, texture_gl
->t
.resource
.height
);
2178 checkGLcall("glRenderbufferStorage()");
2179 TRACE("Created resolved rb %u.\n", texture_gl
->rb_resolved
);
2183 BOOL
wined3d_texture_prepare_location(struct wined3d_texture
*texture
,
2184 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
2186 return texture
->texture_ops
->texture_prepare_location(texture
, sub_resource_idx
, context
, location
);
2189 static void wined3d_texture_unload_location(struct wined3d_texture
*texture
,
2190 struct wined3d_context
*context
, unsigned int location
)
2192 texture
->texture_ops
->texture_unload_location(texture
, context
, location
);
2195 static struct wined3d_texture_sub_resource
*wined3d_texture_get_sub_resource(struct wined3d_texture
*texture
,
2196 unsigned int sub_resource_idx
)
2198 UINT sub_count
= texture
->level_count
* texture
->layer_count
;
2200 TRACE("texture %p, sub_resource_idx %u.\n", texture
, sub_resource_idx
);
2202 if (sub_resource_idx
>= sub_count
)
2204 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
2208 return &texture
->sub_resources
[sub_resource_idx
];
2211 static void wined3d_texture_dirty_region_add(struct wined3d_texture
*texture
,
2212 unsigned int layer
, const struct wined3d_box
*box
)
2214 struct wined3d_dirty_regions
*regions
;
2217 if (!texture
->dirty_regions
)
2220 regions
= &texture
->dirty_regions
[layer
];
2221 count
= regions
->box_count
+ 1;
2222 if (count
>= WINED3D_MAX_DIRTY_REGION_COUNT
|| !box
2223 || (!box
->left
&& !box
->top
&& !box
->front
2224 && box
->right
== texture
->resource
.width
2225 && box
->bottom
== texture
->resource
.height
2226 && box
->back
== texture
->resource
.depth
))
2228 regions
->box_count
= WINED3D_MAX_DIRTY_REGION_COUNT
;
2232 if (!wined3d_array_reserve((void **)®ions
->boxes
, ®ions
->boxes_size
, count
, sizeof(*regions
->boxes
)))
2234 WARN("Failed to grow boxes array, marking entire texture dirty.\n");
2235 regions
->box_count
= WINED3D_MAX_DIRTY_REGION_COUNT
;
2239 regions
->boxes
[regions
->box_count
++] = *box
;
2242 HRESULT CDECL
wined3d_texture_add_dirty_region(struct wined3d_texture
*texture
,
2243 UINT layer
, const struct wined3d_box
*dirty_region
)
2245 TRACE("texture %p, layer %u, dirty_region %s.\n", texture
, layer
, debug_box(dirty_region
));
2247 if (layer
>= texture
->layer_count
)
2249 WARN("Invalid layer %u specified.\n", layer
);
2250 return WINED3DERR_INVALIDCALL
;
2253 if (dirty_region
&& FAILED(wined3d_texture_check_box_dimensions(texture
, 0, dirty_region
)))
2255 WARN("Invalid dirty_region %s specified.\n", debug_box(dirty_region
));
2256 return WINED3DERR_INVALIDCALL
;
2259 wined3d_texture_dirty_region_add(texture
, layer
, dirty_region
);
2260 wined3d_cs_emit_add_dirty_texture_region(texture
->resource
.device
->cs
, texture
, layer
);
2265 static void wined3d_texture_gl_upload_bo(const struct wined3d_format
*src_format
, GLenum target
,
2266 unsigned int level
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
2267 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
, unsigned int update_w
,
2268 unsigned int update_h
, unsigned int update_d
, const BYTE
*addr
, BOOL srgb
,
2269 struct wined3d_texture
*dst_texture
, const struct wined3d_gl_info
*gl_info
)
2271 const struct wined3d_format_gl
*format_gl
= wined3d_format_gl(src_format
);
2273 if (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
2275 GLenum internal
= wined3d_gl_get_internal_format(&dst_texture
->resource
, format_gl
, srgb
);
2276 unsigned int dst_row_pitch
, dst_slice_pitch
;
2278 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
, &dst_row_pitch
, &dst_slice_pitch
);
2280 TRACE("Uploading compressed data, target %#x, level %u, x %u, y %u, z %u, "
2281 "w %u, h %u, d %u, format %#x, image_size %#x, addr %p.\n",
2282 target
, level
, dst_x
, dst_y
, dst_z
, update_w
, update_h
,
2283 update_d
, internal
, dst_slice_pitch
, addr
);
2285 if (target
== GL_TEXTURE_1D
)
2287 GL_EXTCALL(glCompressedTexSubImage1D(target
, level
, dst_x
,
2288 update_w
, internal
, dst_row_pitch
, addr
));
2292 unsigned int row
, y
, slice
, slice_count
= 1, row_count
= 1;
2294 /* glCompressedTexSubImage2D() ignores pixel store state, so we
2295 * can't use the unpack row length like for glTexSubImage2D. */
2296 if (dst_row_pitch
!= src_row_pitch
)
2298 row_count
= (update_h
+ src_format
->block_height
- 1) / src_format
->block_height
;
2299 update_h
= src_format
->block_height
;
2300 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
,
2301 &dst_row_pitch
, &dst_slice_pitch
);
2304 if (dst_slice_pitch
!= src_slice_pitch
)
2306 slice_count
= update_d
;
2310 for (slice
= 0; slice
< slice_count
; ++slice
)
2312 for (row
= 0, y
= dst_y
; row
< row_count
; ++row
)
2314 const BYTE
*upload_addr
= &addr
[slice
* src_slice_pitch
+ row
* src_row_pitch
];
2316 if (target
== GL_TEXTURE_2D_ARRAY
|| target
== GL_TEXTURE_3D
)
2318 GL_EXTCALL(glCompressedTexSubImage3D(target
, level
, dst_x
, y
, dst_z
+ slice
, update_w
,
2319 update_h
, update_d
, internal
, update_d
* dst_slice_pitch
, upload_addr
));
2323 GL_EXTCALL(glCompressedTexSubImage2D(target
, level
, dst_x
, y
, update_w
,
2324 update_h
, internal
, dst_slice_pitch
, upload_addr
));
2327 y
+= src_format
->block_height
;
2331 checkGLcall("Upload compressed texture data");
2335 unsigned int y
, y_count
, z
, z_count
;
2336 bool unpacking_rows
= false;
2338 TRACE("Uploading data, target %#x, level %u, x %u, y %u, z %u, "
2339 "w %u, h %u, d %u, format %#x, type %#x, addr %p.\n",
2340 target
, level
, dst_x
, dst_y
, dst_z
, update_w
, update_h
,
2341 update_d
, format_gl
->format
, format_gl
->type
, addr
);
2343 if (src_row_pitch
&& !(src_row_pitch
% src_format
->byte_count
))
2345 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_ROW_LENGTH
, src_row_pitch
/ src_format
->byte_count
);
2347 unpacking_rows
= true;
2355 if (src_slice_pitch
&& unpacking_rows
&& !(src_slice_pitch
% src_row_pitch
))
2357 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
, src_slice_pitch
/ src_row_pitch
);
2360 else if (src_slice_pitch
&& !unpacking_rows
&& !(src_slice_pitch
% (update_w
* src_format
->byte_count
)))
2362 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
,
2363 src_slice_pitch
/ (update_w
* src_format
->byte_count
));
2372 for (z
= 0; z
< z_count
; ++z
)
2374 for (y
= 0; y
< y_count
; ++y
)
2376 const BYTE
*upload_addr
= &addr
[z
* src_slice_pitch
+ y
* src_row_pitch
];
2377 if (target
== GL_TEXTURE_2D_ARRAY
|| target
== GL_TEXTURE_3D
)
2379 GL_EXTCALL(glTexSubImage3D(target
, level
, dst_x
, dst_y
+ y
, dst_z
+ z
, update_w
,
2380 update_h
, update_d
, format_gl
->format
, format_gl
->type
, upload_addr
));
2382 else if (target
== GL_TEXTURE_1D
)
2384 gl_info
->gl_ops
.gl
.p_glTexSubImage1D(target
, level
, dst_x
,
2385 update_w
, format_gl
->format
, format_gl
->type
, upload_addr
);
2389 gl_info
->gl_ops
.gl
.p_glTexSubImage2D(target
, level
, dst_x
, dst_y
+ y
,
2390 update_w
, update_h
, format_gl
->format
, format_gl
->type
, upload_addr
);
2394 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_ROW_LENGTH
, 0);
2395 gl_info
->gl_ops
.gl
.p_glPixelStorei(GL_UNPACK_IMAGE_HEIGHT
, 0);
2396 checkGLcall("Upload texture data");
2400 static const struct d3dfmt_alpha_fixup
2402 enum wined3d_format_id format_id
, conv_format_id
;
2404 formats_src_alpha_fixup
[] =
2406 {WINED3DFMT_B8G8R8X8_UNORM
, WINED3DFMT_B8G8R8A8_UNORM
},
2407 {WINED3DFMT_B5G5R5X1_UNORM
, WINED3DFMT_B5G5R5A1_UNORM
},
2408 {WINED3DFMT_B4G4R4X4_UNORM
, WINED3DFMT_B4G4R4A4_UNORM
},
2411 static enum wined3d_format_id
wined3d_get_alpha_fixup_format(enum wined3d_format_id format_id
,
2412 const struct wined3d_format
*dst_format
)
2416 if (!(dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
2417 && !dst_format
->alpha_size
)
2418 return WINED3DFMT_UNKNOWN
;
2420 for (i
= 0; i
< ARRAY_SIZE(formats_src_alpha_fixup
); ++i
)
2422 if (formats_src_alpha_fixup
[i
].format_id
== format_id
)
2423 return formats_src_alpha_fixup
[i
].conv_format_id
;
2426 return WINED3DFMT_UNKNOWN
;
2429 static void wined3d_fixup_alpha(const struct wined3d_format
*format
, const uint8_t *src
,
2430 unsigned int src_row_pitch
, uint8_t *dst
, unsigned int dst_row_pitch
,
2431 unsigned int width
, unsigned int height
)
2433 unsigned int byte_count
, alpha_mask
;
2436 byte_count
= format
->byte_count
;
2437 alpha_mask
= ((1u << format
->alpha_size
) - 1) << format
->alpha_offset
;
2442 for (y
= 0; y
< height
; ++y
)
2444 const uint16_t *src_row
= (const uint16_t *)&src
[y
* src_row_pitch
];
2445 uint16_t *dst_row
= (uint16_t *)&dst
[y
* dst_row_pitch
];
2447 for (x
= 0; x
< width
; ++x
)
2449 dst_row
[x
] = src_row
[x
] | alpha_mask
;
2455 for (y
= 0; y
< height
; ++y
)
2457 const uint32_t *src_row
= (const uint32_t *)&src
[y
* src_row_pitch
];
2458 uint32_t *dst_row
= (uint32_t *)&dst
[y
* dst_row_pitch
];
2460 for (x
= 0; x
< width
; ++x
)
2462 dst_row
[x
] = src_row
[x
] | alpha_mask
;
2468 ERR("Unsupported byte count %u.\n", byte_count
);
2473 static void wined3d_texture_gl_upload_data(struct wined3d_context
*context
,
2474 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
2475 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
2476 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
2477 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
2479 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
2480 enum wined3d_format_id alpha_fixup_format_id
= WINED3DFMT_UNKNOWN
;
2481 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2482 unsigned int update_w
= src_box
->right
- src_box
->left
;
2483 unsigned int update_h
= src_box
->bottom
- src_box
->top
;
2484 unsigned int update_d
= src_box
->back
- src_box
->front
;
2485 struct wined3d_bo_address bo
;
2491 TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, "
2492 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n",
2493 context
, debug_const_bo_address(src_bo_addr
), debug_d3dformat(src_format
->id
), debug_box(src_box
),
2494 src_row_pitch
, src_slice_pitch
, dst_texture
, dst_sub_resource_idx
,
2495 wined3d_debug_location(dst_location
), dst_x
, dst_y
, dst_z
);
2497 if (dst_location
== WINED3D_LOCATION_TEXTURE_SRGB
)
2501 else if (dst_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
2503 FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location
));
2507 wined3d_texture_gl_bind_and_dirtify(wined3d_texture_gl(dst_texture
), wined3d_context_gl(context
), srgb
);
2509 if (dst_texture
->sub_resources
[dst_sub_resource_idx
].map_count
)
2511 WARN("Uploading a texture that is currently mapped, setting WINED3D_TEXTURE_PIN_SYSMEM.\n");
2512 dst_texture
->flags
|= WINED3D_TEXTURE_PIN_SYSMEM
;
2515 if (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_HEIGHT_SCALE
)
2517 update_h
*= src_format
->height_scale
.numerator
;
2518 update_h
/= src_format
->height_scale
.denominator
;
2521 target
= wined3d_texture_gl_get_sub_resource_target(wined3d_texture_gl(dst_texture
), dst_sub_resource_idx
);
2522 level
= dst_sub_resource_idx
% dst_texture
->level_count
;
2526 case GL_TEXTURE_1D_ARRAY
:
2527 dst_y
= dst_sub_resource_idx
/ dst_texture
->level_count
;
2530 case GL_TEXTURE_2D_ARRAY
:
2531 dst_z
= dst_sub_resource_idx
/ dst_texture
->level_count
;
2534 case GL_TEXTURE_2D_MULTISAMPLE
:
2535 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
2536 FIXME("Not supported for multisample textures.\n");
2540 bo
.buffer_object
= src_bo_addr
->buffer_object
;
2541 bo
.addr
= (BYTE
*)src_bo_addr
->addr
+ src_box
->front
* src_slice_pitch
;
2542 if (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_BLOCKS
)
2544 bo
.addr
+= (src_box
->top
/ src_format
->block_height
) * src_row_pitch
;
2545 bo
.addr
+= (src_box
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
2549 bo
.addr
+= src_box
->top
* src_row_pitch
;
2550 bo
.addr
+= src_box
->left
* src_format
->byte_count
;
2553 decompress
= (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_DECOMPRESS
)
2554 || (src_format
->decompress
&& src_format
->id
!= dst_texture
->resource
.format
->id
);
2556 if (src_format
->upload
|| decompress
2557 || (alpha_fixup_format_id
= wined3d_get_alpha_fixup_format(src_format
->id
,
2558 dst_texture
->resource
.format
)) != WINED3DFMT_UNKNOWN
)
2560 const struct wined3d_format
*compressed_format
= src_format
;
2561 unsigned int dst_row_pitch
, dst_slice_pitch
;
2562 struct wined3d_format_gl f
;
2563 void *converted_mem
;
2569 src_format
= wined3d_resource_get_decompress_format(&dst_texture
->resource
);
2571 else if (alpha_fixup_format_id
!= WINED3DFMT_UNKNOWN
)
2573 src_format
= wined3d_get_format(context
->device
->adapter
, alpha_fixup_format_id
, 0);
2574 assert(!!src_format
);
2578 if (dst_texture
->resource
.format_flags
& WINED3DFMT_FLAG_BLOCKS
)
2579 ERR("Converting a block-based format.\n");
2581 f
= *wined3d_format_gl(src_format
);
2582 f
.f
.byte_count
= src_format
->conv_byte_count
;
2586 wined3d_format_calculate_pitch(src_format
, 1, update_w
, update_h
, &dst_row_pitch
, &dst_slice_pitch
);
2588 if (!(converted_mem
= heap_alloc(dst_slice_pitch
)))
2590 ERR("Failed to allocate upload buffer.\n");
2594 src_mem
= wined3d_context_gl_map_bo_address(context_gl
, &bo
, src_slice_pitch
* update_d
, WINED3D_MAP_READ
);
2596 for (z
= 0; z
< update_d
; ++z
, src_mem
+= src_slice_pitch
)
2599 compressed_format
->decompress(src_mem
, converted_mem
, src_row_pitch
, src_slice_pitch
,
2600 dst_row_pitch
, dst_slice_pitch
, update_w
, update_h
, 1);
2601 else if (alpha_fixup_format_id
!= WINED3DFMT_UNKNOWN
)
2602 wined3d_fixup_alpha(src_format
, src_mem
, src_row_pitch
, converted_mem
, dst_row_pitch
,
2603 update_w
, update_h
);
2605 src_format
->upload(src_mem
, converted_mem
, src_row_pitch
, src_slice_pitch
,
2606 dst_row_pitch
, dst_slice_pitch
, update_w
, update_h
, 1);
2608 wined3d_texture_gl_upload_bo(src_format
, target
, level
, dst_row_pitch
, dst_slice_pitch
, dst_x
,
2609 dst_y
, dst_z
+ z
, update_w
, update_h
, 1, converted_mem
, srgb
, dst_texture
, gl_info
);
2612 wined3d_context_gl_unmap_bo_address(context_gl
, &bo
, 0, NULL
);
2613 heap_free(converted_mem
);
2617 if (bo
.buffer_object
)
2619 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, ((struct wined3d_bo_gl
*)bo
.buffer_object
)->id
));
2620 checkGLcall("glBindBuffer");
2623 wined3d_texture_gl_upload_bo(src_format
, target
, level
, src_row_pitch
, src_slice_pitch
, dst_x
,
2624 dst_y
, dst_z
, update_w
, update_h
, update_d
, bo
.addr
, srgb
, dst_texture
, gl_info
);
2626 if (bo
.buffer_object
)
2628 GL_EXTCALL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, 0));
2629 wined3d_context_gl_reference_bo(context_gl
, (struct wined3d_bo_gl
*)bo
.buffer_object
);
2630 checkGLcall("glBindBuffer");
2634 if (gl_info
->quirks
& WINED3D_QUIRK_FBO_TEX_UPDATE
)
2636 struct wined3d_device
*device
= dst_texture
->resource
.device
;
2639 for (i
= 0; i
< device
->context_count
; ++i
)
2641 wined3d_context_gl_texture_update(wined3d_context_gl(device
->contexts
[i
]), wined3d_texture_gl(dst_texture
));
2646 static void wined3d_texture_gl_download_data_slow_path(struct wined3d_texture_gl
*texture_gl
,
2647 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, const struct wined3d_bo_address
*data
)
2649 struct wined3d_bo_gl
*bo
= (struct wined3d_bo_gl
*)data
->buffer_object
;
2650 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2651 struct wined3d_texture_sub_resource
*sub_resource
;
2652 unsigned int dst_row_pitch
, dst_slice_pitch
;
2653 unsigned int src_row_pitch
, src_slice_pitch
;
2654 const struct wined3d_format_gl
*format_gl
;
2655 BYTE
*temporary_mem
= NULL
;
2660 format_gl
= wined3d_format_gl(texture_gl
->t
.resource
.format
);
2662 /* Only support read back of converted P8 textures. */
2663 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_CONVERTED
&& format_gl
->f
.id
!= WINED3DFMT_P8_UINT
2664 && !format_gl
->f
.download
)
2666 ERR("Trying to read back converted texture %p, %u with format %s.\n",
2667 texture_gl
, sub_resource_idx
, debug_d3dformat(format_gl
->f
.id
));
2671 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
2672 target
= wined3d_texture_gl_get_sub_resource_target(texture_gl
, sub_resource_idx
);
2673 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
2675 if (target
== GL_TEXTURE_1D_ARRAY
|| target
== GL_TEXTURE_2D_ARRAY
)
2677 if (format_gl
->f
.download
)
2679 FIXME("Reading back converted array texture %p is not supported.\n", texture_gl
);
2683 /* NP2 emulation is not allowed on array textures. */
2684 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2685 ERR("Array texture %p uses NP2 emulation.\n", texture_gl
);
2687 WARN_(d3d_perf
)("Downloading all miplevel layers to get the data for a single sub-resource.\n");
2689 if (!(temporary_mem
= heap_calloc(texture_gl
->t
.layer_count
, sub_resource
->size
)))
2691 ERR("Out of memory.\n");
2696 if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2698 if (format_gl
->f
.download
)
2700 FIXME("Reading back converted texture %p with NP2 emulation is not supported.\n", texture_gl
);
2704 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &dst_row_pitch
, &dst_slice_pitch
);
2705 wined3d_format_calculate_pitch(&format_gl
->f
, texture_gl
->t
.resource
.device
->surface_alignment
,
2706 wined3d_texture_get_level_pow2_width(&texture_gl
->t
, level
),
2707 wined3d_texture_get_level_pow2_height(&texture_gl
->t
, level
),
2708 &src_row_pitch
, &src_slice_pitch
);
2709 if (!(temporary_mem
= heap_alloc(src_slice_pitch
)))
2711 ERR("Out of memory.\n");
2716 ERR("NP2 emulated texture uses PBO unexpectedly.\n");
2717 if (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2718 ERR("Unexpected compressed format for NP2 emulated texture.\n");
2721 if (format_gl
->f
.download
)
2723 struct wined3d_format f
;
2726 ERR("Converted texture %p uses PBO unexpectedly.\n", texture_gl
);
2728 WARN_(d3d_perf
)("Downloading converted texture %p, %u with format %s.\n",
2729 texture_gl
, sub_resource_idx
, debug_d3dformat(format_gl
->f
.id
));
2732 f
.byte_count
= format_gl
->f
.conv_byte_count
;
2733 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &dst_row_pitch
, &dst_slice_pitch
);
2734 wined3d_format_calculate_pitch(&f
, texture_gl
->t
.resource
.device
->surface_alignment
,
2735 wined3d_texture_get_level_width(&texture_gl
->t
, level
),
2736 wined3d_texture_get_level_height(&texture_gl
->t
, level
),
2737 &src_row_pitch
, &src_slice_pitch
);
2739 if (!(temporary_mem
= heap_alloc(src_slice_pitch
)))
2741 ERR("Failed to allocate memory.\n");
2748 mem
= temporary_mem
;
2752 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, bo
->id
));
2753 checkGLcall("glBindBuffer");
2761 if (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2763 TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2764 texture_gl
, sub_resource_idx
, level
, format_gl
->format
, format_gl
->type
, mem
);
2766 GL_EXTCALL(glGetCompressedTexImage(target
, level
, mem
));
2767 checkGLcall("glGetCompressedTexImage");
2771 TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2772 texture_gl
, sub_resource_idx
, level
, format_gl
->format
, format_gl
->type
, mem
);
2774 gl_info
->gl_ops
.gl
.p_glGetTexImage(target
, level
, format_gl
->format
, format_gl
->type
, mem
);
2775 checkGLcall("glGetTexImage");
2778 if (format_gl
->f
.download
)
2780 format_gl
->f
.download(mem
, data
->addr
, src_row_pitch
, src_slice_pitch
, dst_row_pitch
, dst_slice_pitch
,
2781 wined3d_texture_get_level_width(&texture_gl
->t
, level
),
2782 wined3d_texture_get_level_height(&texture_gl
->t
, level
), 1);
2784 else if (texture_gl
->t
.flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
2786 const BYTE
*src_data
;
2789 /* Some games (e.g. Warhammer 40,000) don't properly handle texture
2790 * pitches, preventing us from using the texture pitch to box NPOT
2791 * textures. Instead, we repack the texture's CPU copy so that its
2792 * pitch equals bpp * width instead of bpp * pow2width.
2794 * Instead of boxing the texture:
2796 * │<── texture width ──>│ pow2 width ──>│
2797 * ├─────────────────────┼───────────────┼─
2798 * │111111111111111111111│ │ʌ
2799 * │222222222222222222222│ ││
2800 * │333333333333333333333│ padding │texture height
2801 * │444444444444444444444│ ││
2802 * │555555555555555555555│ │v
2803 * ├─────────────────────┘ ├─
2804 * │ │pow2 height
2805 * │ padding padding ││
2807 * └─────────────────────────────────────┴─
2809 * we're repacking the data to the expected texture width
2811 * │<── texture width ──>│ pow2 width ──>│
2812 * ├─────────────────────┴───────────────┼─
2813 * │1111111111111111111112222222222222222│ʌ
2814 * │2222233333333333333333333344444444444││
2815 * │4444444444555555555555555555555 │texture height
2817 * │ padding padding │v
2819 * │ │pow2 height
2820 * │ padding padding ││
2822 * └─────────────────────────────────────┴─
2826 * │<── texture width ──>│
2827 * ├─────────────────────┼─
2828 * │111111111111111111111│ʌ
2829 * │222222222222222222222││
2830 * │333333333333333333333│texture height
2831 * │444444444444444444444││
2832 * │555555555555555555555│v
2833 * └─────────────────────┴─
2835 * This also means that any references to surface memory should work
2836 * with the data as if it were a standard texture with a NPOT width
2837 * instead of a texture boxed up to be a power-of-two texture. */
2839 dst_data
= data
->addr
;
2840 TRACE("Repacking the surface data from pitch %u to pitch %u.\n", src_row_pitch
, dst_row_pitch
);
2841 h
= wined3d_texture_get_level_height(&texture_gl
->t
, level
);
2842 for (y
= 0; y
< h
; ++y
)
2844 memcpy(dst_data
, src_data
, dst_row_pitch
);
2845 src_data
+= src_row_pitch
;
2846 dst_data
+= dst_row_pitch
;
2849 else if (temporary_mem
)
2851 unsigned int layer
= sub_resource_idx
/ texture_gl
->t
.level_count
;
2852 void *src_data
= temporary_mem
+ layer
* sub_resource
->size
;
2855 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, bo
->id
));
2856 checkGLcall("glBindBuffer");
2857 GL_EXTCALL(glBufferSubData(GL_PIXEL_PACK_BUFFER
, 0, sub_resource
->size
, src_data
));
2858 checkGLcall("glBufferSubData");
2862 memcpy(data
->addr
, src_data
, sub_resource
->size
);
2868 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0));
2869 wined3d_context_gl_reference_bo(context_gl
, bo
);
2870 checkGLcall("glBindBuffer");
2873 heap_free(temporary_mem
);
2876 static void wined3d_texture_gl_download_data(struct wined3d_context
*context
,
2877 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
2878 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
2879 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
2880 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
2882 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
2883 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
2884 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
2885 unsigned int src_level
, src_width
, src_height
, src_depth
;
2886 unsigned int src_row_pitch
, src_slice_pitch
;
2887 const struct wined3d_format_gl
*format_gl
;
2888 struct wined3d_bo_gl
*dst_bo
;
2892 TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, "
2893 "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n",
2894 context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
2895 debug_box(src_box
), debug_bo_address(dst_bo_addr
), debug_d3dformat(dst_format
->id
),
2896 dst_x
, dst_y
, dst_z
, dst_row_pitch
, dst_slice_pitch
);
2898 if (src_location
== WINED3D_LOCATION_TEXTURE_SRGB
)
2902 else if (src_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
2904 FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location
));
2908 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
2909 src_width
= wined3d_texture_get_level_width(src_texture
, src_level
);
2910 src_height
= wined3d_texture_get_level_height(src_texture
, src_level
);
2911 src_depth
= wined3d_texture_get_level_depth(src_texture
, src_level
);
2912 if (src_box
->left
|| src_box
->top
|| src_box
->right
!= src_width
|| src_box
->bottom
!= src_height
2913 || src_box
->front
|| src_box
->back
!= src_depth
)
2915 FIXME("Unhandled source box %s.\n", debug_box(src_box
));
2919 if (dst_x
|| dst_y
|| dst_z
)
2921 FIXME("Unhandled destination (%u, %u, %u).\n", dst_x
, dst_y
, dst_z
);
2925 if (dst_format
->id
!= src_texture
->resource
.format
->id
)
2927 FIXME("Unhandled format conversion (%s -> %s).\n",
2928 debug_d3dformat(src_texture
->resource
.format
->id
),
2929 debug_d3dformat(dst_format
->id
));
2933 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
2934 if (src_row_pitch
!= dst_row_pitch
|| src_slice_pitch
!= dst_slice_pitch
)
2936 FIXME("Unhandled destination pitches %u/%u (source pitches %u/%u).\n",
2937 dst_row_pitch
, dst_slice_pitch
, src_row_pitch
, src_slice_pitch
);
2941 wined3d_texture_gl_bind_and_dirtify(src_texture_gl
, context_gl
, srgb
);
2943 format_gl
= wined3d_format_gl(src_texture
->resource
.format
);
2944 target
= wined3d_texture_gl_get_sub_resource_target(src_texture_gl
, src_sub_resource_idx
);
2946 if ((src_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_2D
2947 && (target
== GL_TEXTURE_2D_ARRAY
|| format_gl
->f
.conv_byte_count
2948 || src_texture
->flags
& (WINED3D_TEXTURE_CONVERTED
| WINED3D_TEXTURE_COND_NP2_EMULATED
)))
2949 || target
== GL_TEXTURE_1D_ARRAY
)
2951 wined3d_texture_gl_download_data_slow_path(src_texture_gl
, src_sub_resource_idx
, context_gl
, dst_bo_addr
);
2955 if (format_gl
->f
.conv_byte_count
)
2957 FIXME("Attempting to download a converted texture, type %s format %s.\n",
2958 debug_d3dresourcetype(src_texture
->resource
.type
),
2959 debug_d3dformat(format_gl
->f
.id
));
2963 if ((dst_bo
= (struct wined3d_bo_gl
*)dst_bo_addr
->buffer_object
))
2965 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, dst_bo
->id
));
2966 checkGLcall("glBindBuffer");
2969 if (src_texture
->resource
.format_flags
& WINED3DFMT_FLAG_COMPRESSED
)
2971 TRACE("Downloading compressed texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2972 src_texture
, src_sub_resource_idx
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2974 GL_EXTCALL(glGetCompressedTexImage(target
, src_level
, dst_bo_addr
->addr
));
2975 checkGLcall("glGetCompressedTexImage");
2979 TRACE("Downloading texture %p, %u, level %u, format %#x, type %#x, data %p.\n",
2980 src_texture
, src_sub_resource_idx
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2982 gl_info
->gl_ops
.gl
.p_glGetTexImage(target
, src_level
, format_gl
->format
, format_gl
->type
, dst_bo_addr
->addr
);
2983 checkGLcall("glGetTexImage");
2988 GL_EXTCALL(glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0));
2989 wined3d_context_gl_reference_bo(context_gl
, dst_bo
);
2990 checkGLcall("glBindBuffer");
2994 /* Context activation is done by the caller. */
2995 static BOOL
wined3d_texture_gl_load_sysmem(struct wined3d_texture_gl
*texture_gl
,
2996 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, DWORD dst_location
)
2998 struct wined3d_texture_sub_resource
*sub_resource
;
3000 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
3002 /* We cannot download data from multisample textures directly. */
3003 if (wined3d_texture_gl_is_multisample_location(texture_gl
, WINED3D_LOCATION_TEXTURE_RGB
))
3005 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_RB_RESOLVED
);
3006 texture2d_read_from_framebuffer(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
,
3007 WINED3D_LOCATION_RB_RESOLVED
, dst_location
);
3011 if (sub_resource
->locations
& (WINED3D_LOCATION_RB_MULTISAMPLE
| WINED3D_LOCATION_RB_RESOLVED
))
3012 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_TEXTURE_RGB
);
3014 /* Download the sub-resource to system memory. */
3015 if (sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
))
3017 unsigned int row_pitch
, slice_pitch
, level
;
3018 struct wined3d_bo_address data
;
3019 struct wined3d_box src_box
;
3020 unsigned int src_location
;
3022 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
3023 wined3d_texture_get_memory(&texture_gl
->t
, sub_resource_idx
, &data
, dst_location
);
3024 src_location
= sub_resource
->locations
& WINED3D_LOCATION_TEXTURE_RGB
3025 ? WINED3D_LOCATION_TEXTURE_RGB
: WINED3D_LOCATION_TEXTURE_SRGB
;
3026 wined3d_texture_get_level_box(&texture_gl
->t
, level
, &src_box
);
3027 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &row_pitch
, &slice_pitch
);
3028 wined3d_texture_gl_download_data(&context_gl
->c
, &texture_gl
->t
, sub_resource_idx
, src_location
,
3029 &src_box
, &data
, texture_gl
->t
.resource
.format
, 0, 0, 0, row_pitch
, slice_pitch
);
3031 ++texture_gl
->t
.download_count
;
3035 if (!(texture_gl
->t
.resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
3036 && (sub_resource
->locations
& WINED3D_LOCATION_DRAWABLE
))
3038 texture2d_read_from_framebuffer(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
,
3039 texture_gl
->t
.resource
.draw_binding
, dst_location
);
3043 FIXME("Can't load texture %p, %u with location flags %s into sysmem.\n",
3044 texture_gl
, sub_resource_idx
, wined3d_debug_location(sub_resource
->locations
));
3049 static BOOL
wined3d_texture_load_drawable(struct wined3d_texture
*texture
,
3050 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
3052 struct wined3d_device
*device
;
3056 if (texture
->resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
3058 DWORD current
= texture
->sub_resources
[sub_resource_idx
].locations
;
3059 FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
3060 wined3d_debug_location(current
));
3064 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
3065 && wined3d_resource_is_offscreen(&texture
->resource
))
3067 ERR("Trying to load offscreen texture into WINED3D_LOCATION_DRAWABLE.\n");
3071 device
= texture
->resource
.device
;
3072 level
= sub_resource_idx
% texture
->level_count
;
3073 SetRect(&r
, 0, 0, wined3d_texture_get_level_width(texture
, level
),
3074 wined3d_texture_get_level_height(texture
, level
));
3075 wined3d_texture_load_location(texture
, sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
3076 device
->blitter
->ops
->blitter_blit(device
->blitter
, WINED3D_BLIT_OP_COLOR_BLIT
, context
,
3077 texture
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &r
,
3078 texture
, sub_resource_idx
, WINED3D_LOCATION_DRAWABLE
, &r
,
3079 NULL
, WINED3D_TEXF_POINT
, NULL
);
3084 static BOOL
wined3d_texture_load_renderbuffer(struct wined3d_texture
*texture
,
3085 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD dst_location
)
3087 unsigned int level
= sub_resource_idx
% texture
->level_count
;
3088 const RECT rect
= {0, 0,
3089 wined3d_texture_get_level_width(texture
, level
),
3090 wined3d_texture_get_level_height(texture
, level
)};
3091 struct wined3d_texture_sub_resource
*sub_resource
;
3092 DWORD src_location
, locations
;
3094 sub_resource
= &texture
->sub_resources
[sub_resource_idx
];
3095 locations
= sub_resource
->locations
;
3096 if (texture
->resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
3098 FIXME("Unimplemented copy from %s for depth/stencil buffers.\n",
3099 wined3d_debug_location(locations
));
3103 if (locations
& WINED3D_LOCATION_RB_MULTISAMPLE
)
3104 src_location
= WINED3D_LOCATION_RB_MULTISAMPLE
;
3105 else if (locations
& WINED3D_LOCATION_RB_RESOLVED
)
3106 src_location
= WINED3D_LOCATION_RB_RESOLVED
;
3107 else if (locations
& WINED3D_LOCATION_TEXTURE_SRGB
)
3108 src_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
3109 else if (locations
& WINED3D_LOCATION_TEXTURE_RGB
)
3110 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3111 else if (locations
& WINED3D_LOCATION_DRAWABLE
)
3112 src_location
= WINED3D_LOCATION_DRAWABLE
;
3113 else /* texture2d_blt_fbo() will load the source location if necessary. */
3114 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3116 texture2d_blt_fbo(texture
->resource
.device
, context
, WINED3D_TEXF_POINT
, texture
,
3117 sub_resource_idx
, src_location
, &rect
, texture
, sub_resource_idx
, dst_location
, &rect
, NULL
);
3122 static BOOL
wined3d_texture_gl_load_texture(struct wined3d_texture_gl
*texture_gl
,
3123 unsigned int sub_resource_idx
, struct wined3d_context_gl
*context_gl
, BOOL srgb
)
3125 unsigned int width
, height
, level
, src_row_pitch
, src_slice_pitch
, dst_row_pitch
, dst_slice_pitch
;
3126 struct wined3d_device
*device
= texture_gl
->t
.resource
.device
;
3127 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
3128 const struct wined3d_color_key_conversion
*conversion
;
3129 struct wined3d_texture_sub_resource
*sub_resource
;
3130 const struct wined3d_format
*format
;
3131 struct wined3d_bo_address data
;
3132 BYTE
*src_mem
, *dst_mem
= NULL
;
3133 struct wined3d_box src_box
;
3137 depth
= texture_gl
->t
.resource
.bind_flags
& WINED3D_BIND_DEPTH_STENCIL
;
3138 sub_resource
= &texture_gl
->t
.sub_resources
[sub_resource_idx
];
3140 if (!depth
&& wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
3141 && wined3d_resource_is_offscreen(&texture_gl
->t
.resource
)
3142 && (sub_resource
->locations
& WINED3D_LOCATION_DRAWABLE
))
3144 texture2d_load_fb_texture(texture_gl
, sub_resource_idx
, srgb
, &context_gl
->c
);
3149 level
= sub_resource_idx
% texture_gl
->t
.level_count
;
3150 wined3d_texture_get_level_box(&texture_gl
->t
, level
, &src_box
);
3152 if (!depth
&& sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_SRGB
| WINED3D_LOCATION_TEXTURE_RGB
)
3153 && (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB
)
3154 && fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT
, gl_info
,
3155 &texture_gl
->t
.resource
, WINED3D_LOCATION_TEXTURE_RGB
,
3156 &texture_gl
->t
.resource
, WINED3D_LOCATION_TEXTURE_SRGB
))
3160 SetRect(&src_rect
, src_box
.left
, src_box
.top
, src_box
.right
, src_box
.bottom
);
3162 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
,
3163 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &src_rect
,
3164 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_SRGB
, &src_rect
, NULL
);
3166 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
,
3167 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_SRGB
, &src_rect
,
3168 &texture_gl
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, &src_rect
, NULL
);
3173 if (!depth
&& sub_resource
->locations
& (WINED3D_LOCATION_RB_MULTISAMPLE
| WINED3D_LOCATION_RB_RESOLVED
)
3174 && (!srgb
|| (texture_gl
->t
.resource
.format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB
)))
3176 DWORD src_location
= sub_resource
->locations
& WINED3D_LOCATION_RB_RESOLVED
?
3177 WINED3D_LOCATION_RB_RESOLVED
: WINED3D_LOCATION_RB_MULTISAMPLE
;
3180 SetRect(&src_rect
, src_box
.left
, src_box
.top
, src_box
.right
, src_box
.bottom
);
3181 dst_location
= srgb
? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
3182 if (fbo_blitter_supported(WINED3D_BLIT_OP_COLOR_BLIT
, gl_info
,
3183 &texture_gl
->t
.resource
, src_location
, &texture_gl
->t
.resource
, dst_location
))
3184 texture2d_blt_fbo(device
, &context_gl
->c
, WINED3D_TEXF_POINT
, &texture_gl
->t
, sub_resource_idx
,
3185 src_location
, &src_rect
, &texture_gl
->t
, sub_resource_idx
, dst_location
, &src_rect
, NULL
);
3190 /* Upload from system memory */
3194 dst_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
3195 if ((sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_RGB
| texture_gl
->t
.resource
.map_binding
))
3196 == WINED3D_LOCATION_TEXTURE_RGB
)
3198 FIXME_(d3d_perf
)("Downloading RGB texture %p, %u to reload it as sRGB.\n", texture_gl
, sub_resource_idx
);
3199 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
,
3200 &context_gl
->c
, texture_gl
->t
.resource
.map_binding
);
3205 dst_location
= WINED3D_LOCATION_TEXTURE_RGB
;
3206 if ((sub_resource
->locations
& (WINED3D_LOCATION_TEXTURE_SRGB
| texture_gl
->t
.resource
.map_binding
))
3207 == WINED3D_LOCATION_TEXTURE_SRGB
)
3209 FIXME_(d3d_perf
)("Downloading sRGB texture %p, %u to reload it as RGB.\n", texture_gl
, sub_resource_idx
);
3210 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
,
3211 &context_gl
->c
, texture_gl
->t
.resource
.map_binding
);
3215 if (!(sub_resource
->locations
& wined3d_texture_sysmem_locations
))
3217 WARN("Trying to load a texture from sysmem, but no simple location is valid.\n");
3218 /* Lets hope we get it from somewhere... */
3219 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_SYSMEM
);
3222 wined3d_texture_get_pitch(&texture_gl
->t
, level
, &src_row_pitch
, &src_slice_pitch
);
3224 format
= texture_gl
->t
.resource
.format
;
3225 if ((conversion
= wined3d_format_get_color_key_conversion(&texture_gl
->t
, TRUE
)))
3226 format
= wined3d_get_format(device
->adapter
, conversion
->dst_format
, texture_gl
->t
.resource
.bind_flags
);
3228 /* Don't use PBOs for converted surfaces. During PBO conversion we look at
3229 * WINED3D_TEXTURE_CONVERTED but it isn't set (yet) in all cases it is
3230 * getting called. */
3231 if (conversion
&& sub_resource
->bo
.id
)
3233 TRACE("Removing the pbo attached to texture %p, %u.\n", texture_gl
, sub_resource_idx
);
3235 wined3d_texture_load_location(&texture_gl
->t
, sub_resource_idx
, &context_gl
->c
, WINED3D_LOCATION_SYSMEM
);
3236 wined3d_texture_set_map_binding(&texture_gl
->t
, WINED3D_LOCATION_SYSMEM
);
3239 wined3d_texture_get_memory(&texture_gl
->t
, sub_resource_idx
, &data
, sub_resource
->locations
);
3242 width
= src_box
.right
- src_box
.left
;
3243 height
= src_box
.bottom
- src_box
.top
;
3244 wined3d_format_calculate_pitch(format
, device
->surface_alignment
,
3245 width
, height
, &dst_row_pitch
, &dst_slice_pitch
);
3247 src_mem
= wined3d_context_gl_map_bo_address(context_gl
, &data
, src_slice_pitch
, WINED3D_MAP_READ
);
3248 if (!(dst_mem
= heap_alloc(dst_slice_pitch
)))
3250 ERR("Out of memory (%u).\n", dst_slice_pitch
);
3253 conversion
->convert(src_mem
, src_row_pitch
, dst_mem
, dst_row_pitch
,
3254 width
, height
, &texture_gl
->t
.async
.gl_color_key
);
3255 src_row_pitch
= dst_row_pitch
;
3256 src_slice_pitch
= dst_slice_pitch
;
3257 wined3d_context_gl_unmap_bo_address(context_gl
, &data
, 0, NULL
);
3259 data
.buffer_object
= 0;
3260 data
.addr
= dst_mem
;
3263 wined3d_texture_gl_upload_data(&context_gl
->c
, wined3d_const_bo_address(&data
), format
, &src_box
,
3264 src_row_pitch
, src_slice_pitch
, &texture_gl
->t
, sub_resource_idx
, dst_location
, 0, 0, 0);
3271 static BOOL
wined3d_texture_gl_prepare_location(struct wined3d_texture
*texture
,
3272 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
3274 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3275 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3279 case WINED3D_LOCATION_SYSMEM
:
3280 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
3281 : wined3d_resource_prepare_sysmem(&texture
->resource
);
3283 case WINED3D_LOCATION_BUFFER
:
3284 wined3d_texture_gl_prepare_buffer_object(texture_gl
, sub_resource_idx
, context_gl
);
3287 case WINED3D_LOCATION_TEXTURE_RGB
:
3288 wined3d_texture_gl_prepare_texture(texture_gl
, context_gl
, FALSE
);
3291 case WINED3D_LOCATION_TEXTURE_SRGB
:
3292 wined3d_texture_gl_prepare_texture(texture_gl
, context_gl
, TRUE
);
3295 case WINED3D_LOCATION_DRAWABLE
:
3296 if (!texture
->swapchain
&& wined3d_settings
.offscreen_rendering_mode
!= ORM_BACKBUFFER
)
3297 ERR("Texture %p does not have a drawable.\n", texture
);
3300 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3301 wined3d_texture_gl_prepare_rb(texture_gl
, context_gl
->gl_info
, TRUE
);
3304 case WINED3D_LOCATION_RB_RESOLVED
:
3305 wined3d_texture_gl_prepare_rb(texture_gl
, context_gl
->gl_info
, FALSE
);
3309 ERR("Invalid location %s.\n", wined3d_debug_location(location
));
3314 /* Context activation is done by the caller. */
3315 static BOOL
wined3d_texture_gl_load_location(struct wined3d_texture
*texture
,
3316 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
3318 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3319 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3321 TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
3322 texture
, sub_resource_idx
, context
, wined3d_debug_location(location
));
3324 if (!wined3d_texture_gl_prepare_location(texture
, sub_resource_idx
, context
, location
))
3329 case WINED3D_LOCATION_SYSMEM
:
3330 case WINED3D_LOCATION_BUFFER
:
3331 return wined3d_texture_gl_load_sysmem(texture_gl
, sub_resource_idx
, context_gl
, location
);
3333 case WINED3D_LOCATION_DRAWABLE
:
3334 return wined3d_texture_load_drawable(texture
, sub_resource_idx
, context
);
3336 case WINED3D_LOCATION_RB_RESOLVED
:
3337 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3338 return wined3d_texture_load_renderbuffer(texture
, sub_resource_idx
, context
, location
);
3340 case WINED3D_LOCATION_TEXTURE_RGB
:
3341 case WINED3D_LOCATION_TEXTURE_SRGB
:
3342 return wined3d_texture_gl_load_texture(texture_gl
, sub_resource_idx
,
3343 context_gl
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
3346 FIXME("Unhandled %s load from %s.\n", wined3d_debug_location(location
),
3347 wined3d_debug_location(texture
->sub_resources
[sub_resource_idx
].locations
));
3352 static void wined3d_texture_gl_unload_location(struct wined3d_texture
*texture
,
3353 struct wined3d_context
*context
, unsigned int location
)
3355 struct wined3d_texture_gl
*texture_gl
= wined3d_texture_gl(texture
);
3356 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
3357 struct wined3d_renderbuffer_entry
*entry
, *entry2
;
3358 unsigned int i
, sub_count
;
3360 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
3364 case WINED3D_LOCATION_BUFFER
:
3365 sub_count
= texture
->level_count
* texture
->layer_count
;
3366 for (i
= 0; i
< sub_count
; ++i
)
3368 if (texture_gl
->t
.sub_resources
[i
].bo
.id
)
3369 wined3d_texture_remove_buffer_object(&texture_gl
->t
, i
, context_gl
);
3373 case WINED3D_LOCATION_TEXTURE_RGB
:
3374 if (texture_gl
->texture_rgb
.name
)
3375 gltexture_delete(texture_gl
->t
.resource
.device
, context_gl
->gl_info
, &texture_gl
->texture_rgb
);
3378 case WINED3D_LOCATION_TEXTURE_SRGB
:
3379 if (texture_gl
->texture_srgb
.name
)
3380 gltexture_delete(texture_gl
->t
.resource
.device
, context_gl
->gl_info
, &texture_gl
->texture_srgb
);
3383 case WINED3D_LOCATION_RB_MULTISAMPLE
:
3384 if (texture_gl
->rb_multisample
)
3386 TRACE("Deleting multisample renderbuffer %u.\n", texture_gl
->rb_multisample
);
3387 context_gl_resource_released(texture_gl
->t
.resource
.device
, texture_gl
->rb_multisample
, TRUE
);
3388 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &texture_gl
->rb_multisample
);
3389 texture_gl
->rb_multisample
= 0;
3393 case WINED3D_LOCATION_RB_RESOLVED
:
3394 LIST_FOR_EACH_ENTRY_SAFE(entry
, entry2
, &texture_gl
->renderbuffers
,
3395 struct wined3d_renderbuffer_entry
, entry
)
3397 context_gl_resource_released(texture_gl
->t
.resource
.device
, entry
->id
, TRUE
);
3398 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &entry
->id
);
3399 list_remove(&entry
->entry
);
3402 list_init(&texture_gl
->renderbuffers
);
3403 texture_gl
->current_renderbuffer
= NULL
;
3405 if (texture_gl
->rb_resolved
)
3407 TRACE("Deleting resolved renderbuffer %u.\n", texture_gl
->rb_resolved
);
3408 context_gl_resource_released(texture_gl
->t
.resource
.device
, texture_gl
->rb_resolved
, TRUE
);
3409 context_gl
->gl_info
->fbo_ops
.glDeleteRenderbuffers(1, &texture_gl
->rb_resolved
);
3410 texture_gl
->rb_resolved
= 0;
3415 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
3420 static const struct wined3d_texture_ops texture_gl_ops
=
3422 wined3d_texture_gl_prepare_location
,
3423 wined3d_texture_gl_load_location
,
3424 wined3d_texture_gl_unload_location
,
3425 wined3d_texture_gl_upload_data
,
3426 wined3d_texture_gl_download_data
,
3429 struct wined3d_texture
* __cdecl
wined3d_texture_from_resource(struct wined3d_resource
*resource
)
3431 return texture_from_resource(resource
);
3434 static ULONG
texture_resource_incref(struct wined3d_resource
*resource
)
3436 return wined3d_texture_incref(texture_from_resource(resource
));
3439 static ULONG
texture_resource_decref(struct wined3d_resource
*resource
)
3441 return wined3d_texture_decref(texture_from_resource(resource
));
3444 static void texture_resource_preload(struct wined3d_resource
*resource
)
3446 struct wined3d_texture
*texture
= texture_from_resource(resource
);
3447 struct wined3d_context
*context
;
3449 context
= context_acquire(resource
->device
, NULL
, 0);
3450 wined3d_texture_load(texture
, context
, texture
->flags
& WINED3D_TEXTURE_IS_SRGB
);
3451 context_release(context
);
3454 static void texture_resource_unload(struct wined3d_resource
*resource
)
3456 struct wined3d_texture
*texture
= texture_from_resource(resource
);
3457 struct wined3d_device
*device
= resource
->device
;
3458 unsigned int location
= resource
->map_binding
;
3459 struct wined3d_context
*context
;
3460 unsigned int sub_count
, i
;
3462 TRACE("resource %p.\n", resource
);
3464 /* D3D is not initialised, so no GPU locations should currently exist.
3465 * Moreover, we may not be able to acquire a valid context. */
3466 if (!device
->d3d_initialized
)
3469 context
= context_acquire(device
, NULL
, 0);
3471 if (location
== WINED3D_LOCATION_BUFFER
)
3472 location
= WINED3D_LOCATION_SYSMEM
;
3474 sub_count
= texture
->level_count
* texture
->layer_count
;
3475 for (i
= 0; i
< sub_count
; ++i
)
3477 if (resource
->access
& WINED3D_RESOURCE_ACCESS_CPU
3478 && wined3d_texture_load_location(texture
, i
, context
, location
))
3480 wined3d_texture_invalidate_location(texture
, i
, ~location
);
3484 if (resource
->access
& WINED3D_RESOURCE_ACCESS_CPU
)
3485 ERR("Discarding %s %p sub-resource %u with resource access %s.\n",
3486 debug_d3dresourcetype(resource
->type
), resource
, i
,
3487 wined3d_debug_resource_access(resource
->access
));
3488 wined3d_texture_validate_location(texture
, i
, WINED3D_LOCATION_DISCARDED
);
3489 wined3d_texture_invalidate_location(texture
, i
, ~WINED3D_LOCATION_DISCARDED
);
3493 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_BUFFER
);
3494 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
3495 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_TEXTURE_SRGB
);
3496 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_RB_MULTISAMPLE
);
3497 wined3d_texture_unload_location(texture
, context
, WINED3D_LOCATION_RB_RESOLVED
);
3499 context_release(context
);
3501 wined3d_texture_force_reload(texture
);
3502 if (texture
->resource
.bind_count
)
3503 device_invalidate_state(device
, STATE_SAMPLER(texture
->sampler
));
3504 wined3d_texture_set_dirty(texture
);
3506 resource_unload(&texture
->resource
);
3509 static HRESULT
texture_resource_sub_resource_map(struct wined3d_resource
*resource
, unsigned int sub_resource_idx
,
3510 struct wined3d_map_desc
*map_desc
, const struct wined3d_box
*box
, DWORD flags
)
3512 const struct wined3d_format
*format
= resource
->format
;
3513 struct wined3d_texture_sub_resource
*sub_resource
;
3514 struct wined3d_device
*device
= resource
->device
;
3515 unsigned int fmt_flags
= resource
->format_flags
;
3516 struct wined3d_context
*context
;
3517 struct wined3d_texture
*texture
;
3518 struct wined3d_bo_address data
;
3519 unsigned int texture_level
;
3523 TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n",
3524 resource
, sub_resource_idx
, map_desc
, debug_box(box
), flags
);
3526 texture
= texture_from_resource(resource
);
3527 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
3528 return E_INVALIDARG
;
3530 texture_level
= sub_resource_idx
% texture
->level_count
;
3531 if (box
&& FAILED(wined3d_texture_check_box_dimensions(texture
, texture_level
, box
)))
3533 WARN("Map box is invalid.\n");
3534 if (((fmt_flags
& WINED3DFMT_FLAG_BLOCKS
) && !(resource
->access
& WINED3D_RESOURCE_ACCESS_CPU
))
3535 || resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
3536 return WINED3DERR_INVALIDCALL
;
3539 if (texture
->flags
& WINED3D_TEXTURE_DC_IN_USE
)
3541 WARN("DC is in use.\n");
3542 return WINED3DERR_INVALIDCALL
;
3545 if (sub_resource
->map_count
)
3547 WARN("Sub-resource is already mapped.\n");
3548 return WINED3DERR_INVALIDCALL
;
3551 context
= context_acquire(device
, NULL
, 0);
3553 if (flags
& WINED3D_MAP_DISCARD
)
3555 TRACE("WINED3D_MAP_DISCARD flag passed, marking %s as up to date.\n",
3556 wined3d_debug_location(resource
->map_binding
));
3557 if ((ret
= wined3d_texture_prepare_location(texture
, sub_resource_idx
, context
, resource
->map_binding
)))
3558 wined3d_texture_validate_location(texture
, sub_resource_idx
, resource
->map_binding
);
3562 if (resource
->usage
& WINED3DUSAGE_DYNAMIC
)
3563 WARN_(d3d_perf
)("Mapping a dynamic texture without WINED3D_MAP_DISCARD.\n");
3564 ret
= wined3d_texture_load_location(texture
, sub_resource_idx
, context
, resource
->map_binding
);
3569 ERR("Failed to prepare location.\n");
3570 context_release(context
);
3571 return E_OUTOFMEMORY
;
3574 /* We only record dirty regions for the top-most level. */
3575 if (texture
->dirty_regions
&& flags
& WINED3D_MAP_WRITE
3576 && !(flags
& WINED3D_MAP_NO_DIRTY_UPDATE
) && !texture_level
)
3577 wined3d_texture_dirty_region_add(texture
, sub_resource_idx
/ texture
->level_count
, box
);
3579 if (flags
& WINED3D_MAP_WRITE
3580 && (!(flags
& WINED3D_MAP_NO_DIRTY_UPDATE
) || (resource
->usage
& WINED3DUSAGE_DYNAMIC
)))
3581 wined3d_texture_invalidate_location(texture
, sub_resource_idx
, ~resource
->map_binding
);
3583 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, resource
->map_binding
);
3584 base_memory
= wined3d_context_map_bo_address(context
, &data
, sub_resource
->size
, flags
);
3585 sub_resource
->map_flags
= flags
;
3586 TRACE("Base memory pointer %p.\n", base_memory
);
3588 context_release(context
);
3590 if (fmt_flags
& WINED3DFMT_FLAG_BROKEN_PITCH
)
3592 map_desc
->row_pitch
= wined3d_texture_get_level_width(texture
, texture_level
) * format
->byte_count
;
3593 map_desc
->slice_pitch
= wined3d_texture_get_level_height(texture
, texture_level
) * map_desc
->row_pitch
;
3597 wined3d_texture_get_pitch(texture
, texture_level
, &map_desc
->row_pitch
, &map_desc
->slice_pitch
);
3602 map_desc
->data
= base_memory
;
3606 if ((fmt_flags
& (WINED3DFMT_FLAG_BLOCKS
| WINED3DFMT_FLAG_BROKEN_PITCH
)) == WINED3DFMT_FLAG_BLOCKS
)
3608 /* Compressed textures are block based, so calculate the offset of
3609 * the block that contains the top-left pixel of the mapped box. */
3610 map_desc
->data
= base_memory
3611 + (box
->front
* map_desc
->slice_pitch
)
3612 + ((box
->top
/ format
->block_height
) * map_desc
->row_pitch
)
3613 + ((box
->left
/ format
->block_width
) * format
->block_byte_count
);
3617 map_desc
->data
= base_memory
3618 + (box
->front
* map_desc
->slice_pitch
)
3619 + (box
->top
* map_desc
->row_pitch
)
3620 + (box
->left
* format
->byte_count
);
3624 if (texture
->swapchain
&& texture
->swapchain
->front_buffer
== texture
)
3626 RECT
*r
= &texture
->swapchain
->front_buffer_update
;
3629 SetRect(r
, 0, 0, resource
->width
, resource
->height
);
3631 SetRect(r
, box
->left
, box
->top
, box
->right
, box
->bottom
);
3632 TRACE("Mapped front buffer %s.\n", wine_dbgstr_rect(r
));
3635 ++resource
->map_count
;
3636 ++sub_resource
->map_count
;
3638 TRACE("Returning memory %p, row pitch %u, slice pitch %u.\n",
3639 map_desc
->data
, map_desc
->row_pitch
, map_desc
->slice_pitch
);
3644 static HRESULT
texture_resource_sub_resource_unmap(struct wined3d_resource
*resource
, unsigned int sub_resource_idx
)
3646 struct wined3d_texture_sub_resource
*sub_resource
;
3647 struct wined3d_device
*device
= resource
->device
;
3648 struct wined3d_context
*context
;
3649 struct wined3d_texture
*texture
;
3650 struct wined3d_bo_address data
;
3651 struct wined3d_range range
;
3653 TRACE("resource %p, sub_resource_idx %u.\n", resource
, sub_resource_idx
);
3655 texture
= texture_from_resource(resource
);
3656 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
3657 return E_INVALIDARG
;
3659 if (!sub_resource
->map_count
)
3661 WARN("Trying to unmap unmapped sub-resource.\n");
3662 if (texture
->flags
& WINED3D_TEXTURE_DC_IN_USE
)
3664 return WINEDDERR_NOTLOCKED
;
3667 context
= context_acquire(device
, NULL
, 0);
3669 wined3d_texture_get_memory(texture
, sub_resource_idx
, &data
, texture
->resource
.map_binding
);
3671 range
.size
= sub_resource
->size
;
3672 wined3d_context_unmap_bo_address(context
, &data
, !!(sub_resource
->map_flags
& WINED3D_MAP_WRITE
), &range
);
3674 context_release(context
);
3676 if (texture
->swapchain
&& texture
->swapchain
->front_buffer
== texture
)
3678 if (!(sub_resource
->locations
& (WINED3D_LOCATION_DRAWABLE
| WINED3D_LOCATION_TEXTURE_RGB
)))
3679 texture
->swapchain
->swapchain_ops
->swapchain_frontbuffer_updated(texture
->swapchain
);
3682 --sub_resource
->map_count
;
3683 if (!--resource
->map_count
&& texture
->update_map_binding
)
3684 wined3d_texture_update_map_binding(texture
);
3689 static const struct wined3d_resource_ops texture_resource_ops
=
3691 texture_resource_incref
,
3692 texture_resource_decref
,
3693 texture_resource_preload
,
3694 texture_resource_unload
,
3695 texture_resource_sub_resource_map
,
3696 texture_resource_sub_resource_unmap
,
3699 static HRESULT
wined3d_texture_init(struct wined3d_texture
*texture
, const struct wined3d_resource_desc
*desc
,
3700 unsigned int layer_count
, unsigned int level_count
, DWORD flags
, struct wined3d_device
*device
,
3701 void *parent
, const struct wined3d_parent_ops
*parent_ops
, void *sub_resources
,
3702 const struct wined3d_texture_ops
*texture_ops
)
3704 const struct wined3d_d3d_info
*d3d_info
= &device
->adapter
->d3d_info
;
3705 struct wined3d_device_parent
*device_parent
= device
->device_parent
;
3706 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
3707 unsigned int sub_count
, i
, j
, size
, offset
= 0;
3708 unsigned int pow2_width
, pow2_height
;
3709 const struct wined3d_format
*format
;
3712 TRACE("texture %p, resource_type %s, format %s, multisample_type %#x, multisample_quality %#x, "
3713 "usage %s, access %s, width %u, height %u, depth %u, layer_count %u, level_count %u, "
3714 "flags %#x, device %p, parent %p, parent_ops %p, sub_resources %p, texture_ops %p.\n",
3715 texture
, debug_d3dresourcetype(desc
->resource_type
), debug_d3dformat(desc
->format
),
3716 desc
->multisample_type
, desc
->multisample_quality
, debug_d3dusage(desc
->usage
),
3717 wined3d_debug_resource_access(desc
->access
), desc
->width
, desc
->height
, desc
->depth
,
3718 layer_count
, level_count
, flags
, device
, parent
, parent_ops
, sub_resources
, texture_ops
);
3720 if (!desc
->width
|| !desc
->height
|| !desc
->depth
)
3721 return WINED3DERR_INVALIDCALL
;
3723 if (desc
->resource_type
== WINED3D_RTYPE_TEXTURE_3D
&& layer_count
!= 1)
3725 ERR("Invalid layer count for volume texture.\n");
3726 return E_INVALIDARG
;
3729 texture
->sub_resources
= sub_resources
;
3731 /* TODO: It should only be possible to create textures for formats
3732 * that are reported as supported. */
3733 if (WINED3DFMT_UNKNOWN
>= desc
->format
)
3735 WARN("Texture cannot be created with a format of WINED3DFMT_UNKNOWN.\n");
3736 return WINED3DERR_INVALIDCALL
;
3738 format
= wined3d_get_format(device
->adapter
, desc
->format
, desc
->bind_flags
);
3740 if (desc
->usage
& WINED3DUSAGE_DYNAMIC
&& (wined3d_resource_access_is_managed(desc
->access
)
3741 || desc
->usage
& WINED3DUSAGE_SCRATCH
))
3743 WARN("Attempted to create a dynamic texture with access %s and usage %s.\n",
3744 wined3d_debug_resource_access(desc
->access
), debug_d3dusage(desc
->usage
));
3745 return WINED3DERR_INVALIDCALL
;
3748 pow2_width
= desc
->width
;
3749 pow2_height
= desc
->height
;
3750 if (((desc
->width
& (desc
->width
- 1)) || (desc
->height
& (desc
->height
- 1)) || (desc
->depth
& (desc
->depth
- 1)))
3751 && !d3d_info
->texture_npot
)
3753 /* level_count == 0 returns an error as well. */
3754 if (level_count
!= 1 || layer_count
!= 1 || desc
->resource_type
== WINED3D_RTYPE_TEXTURE_3D
)
3756 if (!(desc
->usage
& WINED3DUSAGE_SCRATCH
))
3758 WARN("Attempted to create a mipmapped/cube/array/volume NPOT "
3759 "texture without unconditional NPOT support.\n");
3760 return WINED3DERR_INVALIDCALL
;
3763 WARN("Creating a scratch mipmapped/cube/array NPOT texture despite lack of HW support.\n");
3765 texture
->flags
|= WINED3D_TEXTURE_COND_NP2
;
3767 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
&& !d3d_info
->texture_npot_conditional
)
3769 /* TODO: Add support for non-power-of-two compressed textures. */
3770 if (format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
]
3771 & (WINED3DFMT_FLAG_COMPRESSED
| WINED3DFMT_FLAG_HEIGHT_SCALE
))
3773 FIXME("Compressed or height scaled non-power-of-two (%ux%u) textures are not supported.\n",
3774 desc
->width
, desc
->height
);
3775 return WINED3DERR_NOTAVAILABLE
;
3778 /* Find the nearest pow2 match. */
3779 pow2_width
= pow2_height
= 1;
3780 while (pow2_width
< desc
->width
)
3782 while (pow2_height
< desc
->height
)
3784 texture
->flags
|= WINED3D_TEXTURE_COND_NP2_EMULATED
;
3787 texture
->pow2_width
= pow2_width
;
3788 texture
->pow2_height
= pow2_height
;
3790 if ((pow2_width
> d3d_info
->limits
.texture_size
|| pow2_height
> d3d_info
->limits
.texture_size
)
3791 && (desc
->bind_flags
& WINED3D_BIND_SHADER_RESOURCE
))
3793 /* One of four options:
3794 * 1: Do the same as we do with NPOT and scale the texture. (Any
3795 * texture ops would require the texture to be scaled which is
3796 * potentially slow.)
3797 * 2: Set the texture to the maximum size (bad idea).
3798 * 3: WARN and return WINED3DERR_NOTAVAILABLE.
3799 * 4: Create the surface, but allow it to be used only for DirectDraw
3800 * Blts. Some apps (e.g. Swat 3) create textures with a height of
3801 * 16 and a width > 3000 and blt 16x16 letter areas from them to
3802 * the render target. */
3803 if (desc
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
3805 WARN("Dimensions (%ux%u) exceed the maximum texture size.\n", pow2_width
, pow2_height
);
3806 return WINED3DERR_NOTAVAILABLE
;
3809 /* We should never use this surface in combination with OpenGL. */
3810 TRACE("Creating an oversized (%ux%u) surface.\n", pow2_width
, pow2_height
);
3813 for (i
= 0; i
< layer_count
; ++i
)
3815 for (j
= 0; j
< level_count
; ++j
)
3817 unsigned int idx
= i
* level_count
+ j
;
3819 size
= wined3d_format_calculate_size(format
, device
->surface_alignment
,
3820 max(1, desc
->width
>> j
), max(1, desc
->height
>> j
), max(1, desc
->depth
>> j
));
3821 texture
->sub_resources
[idx
].offset
= offset
;
3822 texture
->sub_resources
[idx
].size
= size
;
3825 offset
= (offset
+ (RESOURCE_ALIGNMENT
- 1)) & ~(RESOURCE_ALIGNMENT
- 1);
3829 return WINED3DERR_INVALIDCALL
;
3831 /* Ensure the last mip-level is at least large enough to hold a single
3832 * compressed block. It is questionable how useful these mip-levels are to
3833 * the application with "broken pitch" formats, but we want to avoid
3834 * memory corruption when loading textures into WINED3D_LOCATION_SYSMEM. */
3835 if (format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_BROKEN_PITCH
)
3837 unsigned int min_size
;
3839 min_size
= texture
->sub_resources
[level_count
* layer_count
- 1].offset
+ format
->block_byte_count
;
3840 min_size
= (min_size
+ (RESOURCE_ALIGNMENT
- 1)) & ~(RESOURCE_ALIGNMENT
- 1);
3841 if (min_size
> offset
)
3845 if (FAILED(hr
= resource_init(&texture
->resource
, device
, desc
->resource_type
, format
,
3846 desc
->multisample_type
, desc
->multisample_quality
, desc
->usage
, desc
->bind_flags
, desc
->access
,
3847 desc
->width
, desc
->height
, desc
->depth
, offset
, parent
, parent_ops
, &texture_resource_ops
)))
3849 static unsigned int once
;
3851 /* DXTn 3D textures are not supported. Do not write the ERR for them. */
3852 if ((desc
->format
== WINED3DFMT_DXT1
|| desc
->format
== WINED3DFMT_DXT2
|| desc
->format
== WINED3DFMT_DXT3
3853 || desc
->format
== WINED3DFMT_DXT4
|| desc
->format
== WINED3DFMT_DXT5
)
3854 && !(format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_TEXTURE
)
3855 && desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
&& !once
++)
3856 ERR_(winediag
)("The application tried to create a DXTn texture, but the driver does not support them.\n");
3858 WARN("Failed to initialize resource, returning %#x\n", hr
);
3861 wined3d_resource_update_draw_binding(&texture
->resource
);
3863 texture
->texture_ops
= texture_ops
;
3865 texture
->layer_count
= layer_count
;
3866 texture
->level_count
= level_count
;
3868 texture
->flags
|= WINED3D_TEXTURE_POW2_MAT_IDENT
| WINED3D_TEXTURE_NORMALIZED_COORDS
3869 | WINED3D_TEXTURE_DOWNLOADABLE
;
3870 if (flags
& WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
)
3871 texture
->flags
|= WINED3D_TEXTURE_PIN_SYSMEM
| WINED3D_TEXTURE_GET_DC_LENIENT
;
3872 if (flags
& (WINED3D_TEXTURE_CREATE_GET_DC
| WINED3D_TEXTURE_CREATE_GET_DC_LENIENT
))
3873 texture
->flags
|= WINED3D_TEXTURE_GET_DC
;
3874 if (flags
& WINED3D_TEXTURE_CREATE_DISCARD
)
3875 texture
->flags
|= WINED3D_TEXTURE_DISCARD
;
3876 if (flags
& WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS
)
3878 if (!(texture
->resource
.format_flags
& WINED3DFMT_FLAG_GEN_MIPMAP
))
3879 WARN("Format doesn't support mipmaps generation, "
3880 "ignoring WINED3D_TEXTURE_CREATE_GENERATE_MIPMAPS flag.\n");
3882 texture
->flags
|= WINED3D_TEXTURE_GENERATE_MIPMAPS
;
3885 if (flags
& WINED3D_TEXTURE_CREATE_RECORD_DIRTY_REGIONS
3886 && !(texture
->dirty_regions
= heap_calloc(texture
->layer_count
, sizeof(*texture
->dirty_regions
))))
3888 wined3d_texture_cleanup_sync(texture
);
3889 return E_OUTOFMEMORY
;
3892 /* Precalculated scaling for 'faked' non power of two texture coords. */
3893 if (texture
->resource
.gl_type
== WINED3D_GL_RES_TYPE_TEX_RECT
)
3895 texture
->pow2_matrix
[0] = (float)desc
->width
;
3896 texture
->pow2_matrix
[5] = (float)desc
->height
;
3897 texture
->flags
&= ~(WINED3D_TEXTURE_POW2_MAT_IDENT
| WINED3D_TEXTURE_NORMALIZED_COORDS
);
3899 else if (texture
->flags
& WINED3D_TEXTURE_COND_NP2_EMULATED
)
3901 texture
->pow2_matrix
[0] = (((float)desc
->width
) / ((float)pow2_width
));
3902 texture
->pow2_matrix
[5] = (((float)desc
->height
) / ((float)pow2_height
));
3903 texture
->flags
&= ~WINED3D_TEXTURE_POW2_MAT_IDENT
;
3907 texture
->pow2_matrix
[0] = 1.0f
;
3908 texture
->pow2_matrix
[5] = 1.0f
;
3910 texture
->pow2_matrix
[10] = 1.0f
;
3911 texture
->pow2_matrix
[15] = 1.0f
;
3912 TRACE("x scale %.8e, y scale %.8e.\n", texture
->pow2_matrix
[0], texture
->pow2_matrix
[5]);
3914 if (wined3d_texture_use_pbo(texture
, gl_info
))
3915 texture
->resource
.map_binding
= WINED3D_LOCATION_BUFFER
;
3917 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
3918 || !wined3d_texture_use_pbo(texture
, gl_info
))
3920 if (!wined3d_resource_prepare_sysmem(&texture
->resource
))
3922 wined3d_texture_cleanup_sync(texture
);
3923 return E_OUTOFMEMORY
;
3927 sub_count
= level_count
* layer_count
;
3928 if (sub_count
/ layer_count
!= level_count
)
3930 wined3d_texture_cleanup_sync(texture
);
3931 return E_OUTOFMEMORY
;
3934 if (desc
->usage
& WINED3DUSAGE_OVERLAY
)
3936 if (!(texture
->overlay_info
= heap_calloc(sub_count
, sizeof(*texture
->overlay_info
))))
3938 wined3d_texture_cleanup_sync(texture
);
3939 return E_OUTOFMEMORY
;
3942 for (i
= 0; i
< sub_count
; ++i
)
3944 list_init(&texture
->overlay_info
[i
].entry
);
3945 list_init(&texture
->overlay_info
[i
].overlays
);
3949 /* Generate all sub-resources. */
3950 for (i
= 0; i
< sub_count
; ++i
)
3952 struct wined3d_texture_sub_resource
*sub_resource
;
3954 sub_resource
= &texture
->sub_resources
[i
];
3955 sub_resource
->locations
= WINED3D_LOCATION_DISCARDED
;
3956 if (desc
->resource_type
!= WINED3D_RTYPE_TEXTURE_3D
)
3958 wined3d_texture_validate_location(texture
, i
, WINED3D_LOCATION_SYSMEM
);
3959 wined3d_texture_invalidate_location(texture
, i
, ~WINED3D_LOCATION_SYSMEM
);
3962 if (FAILED(hr
= device_parent
->ops
->texture_sub_resource_created(device_parent
,
3963 desc
->resource_type
, texture
, i
, &sub_resource
->parent
, &sub_resource
->parent_ops
)))
3965 WARN("Failed to create sub-resource parent, hr %#x.\n", hr
);
3966 sub_resource
->parent
= NULL
;
3967 wined3d_texture_cleanup_sync(texture
);
3971 TRACE("parent %p, parent_ops %p.\n", sub_resource
->parent
, sub_resource
->parent_ops
);
3973 TRACE("Created sub-resource %u (level %u, layer %u).\n",
3974 i
, i
% texture
->level_count
, i
/ texture
->level_count
);
3976 if (desc
->usage
& WINED3DUSAGE_OWNDC
)
3978 struct wined3d_texture_idx texture_idx
= {texture
, i
};
3980 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
3981 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
3982 if (!texture
->dc_info
|| !texture
->dc_info
[i
].dc
)
3984 wined3d_texture_cleanup_sync(texture
);
3985 return WINED3DERR_INVALIDCALL
;
3993 HRESULT CDECL
wined3d_device_context_blt(struct wined3d_device_context
*context
,
3994 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, const RECT
*dst_rect
,
3995 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, const RECT
*src_rect
,
3996 unsigned int flags
, const struct wined3d_blt_fx
*fx
, enum wined3d_texture_filter_type filter
)
3998 struct wined3d_box src_box
= {src_rect
->left
, src_rect
->top
, src_rect
->right
, src_rect
->bottom
, 0, 1};
3999 struct wined3d_box dst_box
= {dst_rect
->left
, dst_rect
->top
, dst_rect
->right
, dst_rect
->bottom
, 0, 1};
4002 TRACE("context %p, dst_texture %p, dst_sub_resource_idx %u, dst_rect %s, src_texture %p, "
4003 "src_sub_resource_idx %u, src_rect %s, flags %#x, fx %p, filter %s.\n",
4004 context
, dst_texture
, dst_sub_resource_idx
, wine_dbgstr_rect(dst_rect
), src_texture
,
4005 src_sub_resource_idx
, wine_dbgstr_rect(src_rect
), flags
, fx
, debug_d3dtexturefiltertype(filter
));
4007 if (dst_sub_resource_idx
>= dst_texture
->level_count
* dst_texture
->layer_count
4008 || dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4009 return WINED3DERR_INVALIDCALL
;
4011 if (src_sub_resource_idx
>= src_texture
->level_count
* src_texture
->layer_count
4012 || src_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4013 return WINED3DERR_INVALIDCALL
;
4015 if (filter
!= WINED3D_TEXF_NONE
&& filter
!= WINED3D_TEXF_POINT
4016 && filter
!= WINED3D_TEXF_LINEAR
)
4017 return WINED3DERR_INVALIDCALL
;
4019 if (FAILED(hr
= wined3d_texture_check_box_dimensions(dst_texture
,
4020 dst_sub_resource_idx
% dst_texture
->level_count
, &dst_box
)))
4023 if (FAILED(hr
= wined3d_texture_check_box_dimensions(src_texture
,
4024 src_sub_resource_idx
% src_texture
->level_count
, &src_box
)))
4027 if (dst_texture
->sub_resources
[dst_sub_resource_idx
].map_count
4028 || src_texture
->sub_resources
[src_sub_resource_idx
].map_count
)
4030 WARN("Sub-resource is busy, returning WINEDDERR_SURFACEBUSY.\n");
4031 return WINEDDERR_SURFACEBUSY
;
4034 if (!src_texture
->resource
.format
->depth_size
!= !dst_texture
->resource
.format
->depth_size
4035 || !src_texture
->resource
.format
->stencil_size
!= !dst_texture
->resource
.format
->stencil_size
)
4037 WARN("Rejecting depth/stencil blit between incompatible formats.\n");
4038 return WINED3DERR_INVALIDCALL
;
4041 if (dst_texture
->resource
.device
!= src_texture
->resource
.device
)
4043 FIXME("Rejecting cross-device blit.\n");
4047 wined3d_device_context_emit_blt_sub_resource(&dst_texture
->resource
.device
->cs
->c
, &dst_texture
->resource
,
4048 dst_sub_resource_idx
, &dst_box
, &src_texture
->resource
, src_sub_resource_idx
, &src_box
, flags
, fx
, filter
);
4053 HRESULT CDECL
wined3d_texture_get_overlay_position(const struct wined3d_texture
*texture
,
4054 unsigned int sub_resource_idx
, LONG
*x
, LONG
*y
)
4056 struct wined3d_overlay_info
*overlay
;
4058 TRACE("texture %p, sub_resource_idx %u, x %p, y %p.\n", texture
, sub_resource_idx
, x
, y
);
4060 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
)
4061 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4063 WARN("Invalid sub-resource specified.\n");
4064 return WINEDDERR_NOTAOVERLAYSURFACE
;
4067 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4068 if (!overlay
->dst_texture
)
4070 TRACE("Overlay not visible.\n");
4073 return WINEDDERR_OVERLAYNOTVISIBLE
;
4076 *x
= overlay
->dst_rect
.left
;
4077 *y
= overlay
->dst_rect
.top
;
4079 TRACE("Returning position %d, %d.\n", *x
, *y
);
4084 HRESULT CDECL
wined3d_texture_set_overlay_position(struct wined3d_texture
*texture
,
4085 unsigned int sub_resource_idx
, LONG x
, LONG y
)
4087 struct wined3d_overlay_info
*overlay
;
4090 TRACE("texture %p, sub_resource_idx %u, x %d, y %d.\n", texture
, sub_resource_idx
, x
, y
);
4092 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
)
4093 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4095 WARN("Invalid sub-resource specified.\n");
4096 return WINEDDERR_NOTAOVERLAYSURFACE
;
4099 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4100 w
= overlay
->dst_rect
.right
- overlay
->dst_rect
.left
;
4101 h
= overlay
->dst_rect
.bottom
- overlay
->dst_rect
.top
;
4102 SetRect(&overlay
->dst_rect
, x
, y
, x
+ w
, y
+ h
);
4107 HRESULT CDECL
wined3d_texture_update_overlay(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
,
4108 const RECT
*src_rect
, struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4109 const RECT
*dst_rect
, DWORD flags
)
4111 struct wined3d_overlay_info
*overlay
;
4112 unsigned int level
, dst_level
;
4114 TRACE("texture %p, sub_resource_idx %u, src_rect %s, dst_texture %p, "
4115 "dst_sub_resource_idx %u, dst_rect %s, flags %#x.\n",
4116 texture
, sub_resource_idx
, wine_dbgstr_rect(src_rect
), dst_texture
,
4117 dst_sub_resource_idx
, wine_dbgstr_rect(dst_rect
), flags
);
4119 if (!(texture
->resource
.usage
& WINED3DUSAGE_OVERLAY
) || texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
4120 || sub_resource_idx
>= texture
->level_count
* texture
->layer_count
)
4122 WARN("Invalid sub-resource specified.\n");
4123 return WINEDDERR_NOTAOVERLAYSURFACE
;
4126 if (!dst_texture
|| dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
4127 || dst_sub_resource_idx
>= dst_texture
->level_count
* dst_texture
->layer_count
)
4129 WARN("Invalid destination sub-resource specified.\n");
4130 return WINED3DERR_INVALIDCALL
;
4133 overlay
= &texture
->overlay_info
[sub_resource_idx
];
4135 level
= sub_resource_idx
% texture
->level_count
;
4137 overlay
->src_rect
= *src_rect
;
4139 SetRect(&overlay
->src_rect
, 0, 0,
4140 wined3d_texture_get_level_width(texture
, level
),
4141 wined3d_texture_get_level_height(texture
, level
));
4143 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4145 overlay
->dst_rect
= *dst_rect
;
4147 SetRect(&overlay
->dst_rect
, 0, 0,
4148 wined3d_texture_get_level_width(dst_texture
, dst_level
),
4149 wined3d_texture_get_level_height(dst_texture
, dst_level
));
4151 if (overlay
->dst_texture
&& (overlay
->dst_texture
!= dst_texture
4152 || overlay
->dst_sub_resource_idx
!= dst_sub_resource_idx
|| flags
& WINEDDOVER_HIDE
))
4154 overlay
->dst_texture
= NULL
;
4155 list_remove(&overlay
->entry
);
4158 if (flags
& WINEDDOVER_SHOW
)
4160 if (overlay
->dst_texture
!= dst_texture
|| overlay
->dst_sub_resource_idx
!= dst_sub_resource_idx
)
4162 overlay
->dst_texture
= dst_texture
;
4163 overlay
->dst_sub_resource_idx
= dst_sub_resource_idx
;
4164 list_add_tail(&texture
->overlay_info
[dst_sub_resource_idx
].overlays
, &overlay
->entry
);
4167 else if (flags
& WINEDDOVER_HIDE
)
4169 /* Tests show that the rectangles are erased on hide. */
4170 SetRectEmpty(&overlay
->src_rect
);
4171 SetRectEmpty(&overlay
->dst_rect
);
4172 overlay
->dst_texture
= NULL
;
4178 void * CDECL
wined3d_texture_get_sub_resource_parent(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
)
4180 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4182 TRACE("texture %p, sub_resource_idx %u.\n", texture
, sub_resource_idx
);
4184 if (sub_resource_idx
>= sub_count
)
4186 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4190 return texture
->sub_resources
[sub_resource_idx
].parent
;
4193 void CDECL
wined3d_texture_set_sub_resource_parent(struct wined3d_texture
*texture
,
4194 unsigned int sub_resource_idx
, void *parent
)
4196 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4198 TRACE("texture %p, sub_resource_idx %u, parent %p.\n", texture
, sub_resource_idx
, parent
);
4200 if (sub_resource_idx
>= sub_count
)
4202 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4206 texture
->sub_resources
[sub_resource_idx
].parent
= parent
;
4209 HRESULT CDECL
wined3d_texture_get_sub_resource_desc(const struct wined3d_texture
*texture
,
4210 unsigned int sub_resource_idx
, struct wined3d_sub_resource_desc
*desc
)
4212 unsigned int sub_count
= texture
->level_count
* texture
->layer_count
;
4213 const struct wined3d_resource
*resource
;
4214 unsigned int level_idx
;
4216 TRACE("texture %p, sub_resource_idx %u, desc %p.\n", texture
, sub_resource_idx
, desc
);
4218 if (sub_resource_idx
>= sub_count
)
4220 WARN("sub_resource_idx %u >= sub_count %u.\n", sub_resource_idx
, sub_count
);
4221 return WINED3DERR_INVALIDCALL
;
4224 resource
= &texture
->resource
;
4225 desc
->format
= resource
->format
->id
;
4226 desc
->multisample_type
= resource
->multisample_type
;
4227 desc
->multisample_quality
= resource
->multisample_quality
;
4228 desc
->usage
= resource
->usage
;
4229 desc
->bind_flags
= resource
->bind_flags
;
4230 desc
->access
= resource
->access
;
4232 level_idx
= sub_resource_idx
% texture
->level_count
;
4233 desc
->width
= wined3d_texture_get_level_width(texture
, level_idx
);
4234 desc
->height
= wined3d_texture_get_level_height(texture
, level_idx
);
4235 desc
->depth
= wined3d_texture_get_level_depth(texture
, level_idx
);
4236 desc
->size
= texture
->sub_resources
[sub_resource_idx
].size
;
4241 HRESULT
wined3d_texture_gl_init(struct wined3d_texture_gl
*texture_gl
, struct wined3d_device
*device
,
4242 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
4243 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
4245 const struct wined3d_gl_info
*gl_info
= &device
->adapter
->gl_info
;
4248 TRACE("texture_gl %p, device %p, desc %p, layer_count %u, "
4249 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
4250 texture_gl
, device
, desc
, layer_count
,
4251 level_count
, flags
, parent
, parent_ops
);
4253 if (!(desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
) && layer_count
> 1
4254 && !gl_info
->supported
[EXT_TEXTURE_ARRAY
])
4256 WARN("OpenGL implementation does not support array textures.\n");
4257 return WINED3DERR_INVALIDCALL
;
4260 switch (desc
->resource_type
)
4262 case WINED3D_RTYPE_TEXTURE_1D
:
4263 if (layer_count
> 1)
4264 texture_gl
->target
= GL_TEXTURE_1D_ARRAY
;
4266 texture_gl
->target
= GL_TEXTURE_1D
;
4269 case WINED3D_RTYPE_TEXTURE_2D
:
4270 if (desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
)
4272 texture_gl
->target
= GL_TEXTURE_CUBE_MAP_ARB
;
4274 else if (desc
->multisample_type
&& gl_info
->supported
[ARB_TEXTURE_MULTISAMPLE
])
4276 if (layer_count
> 1)
4277 texture_gl
->target
= GL_TEXTURE_2D_MULTISAMPLE_ARRAY
;
4279 texture_gl
->target
= GL_TEXTURE_2D_MULTISAMPLE
;
4283 if (layer_count
> 1)
4284 texture_gl
->target
= GL_TEXTURE_2D_ARRAY
;
4286 texture_gl
->target
= GL_TEXTURE_2D
;
4290 case WINED3D_RTYPE_TEXTURE_3D
:
4291 if (!gl_info
->supported
[EXT_TEXTURE3D
])
4293 WARN("OpenGL implementation does not support 3D textures.\n");
4294 return WINED3DERR_INVALIDCALL
;
4296 texture_gl
->target
= GL_TEXTURE_3D
;
4300 ERR("Invalid resource type %s.\n", debug_d3dresourcetype(desc
->resource_type
));
4301 return WINED3DERR_INVALIDCALL
;
4304 list_init(&texture_gl
->renderbuffers
);
4306 if (FAILED(hr
= wined3d_texture_init(&texture_gl
->t
, desc
, layer_count
, level_count
,
4307 flags
, device
, parent
, parent_ops
, &texture_gl
[1], &texture_gl_ops
)))
4310 if (texture_gl
->t
.resource
.gl_type
== WINED3D_GL_RES_TYPE_TEX_RECT
)
4311 texture_gl
->target
= GL_TEXTURE_RECTANGLE_ARB
;
4313 if (texture_gl
->target
== GL_TEXTURE_2D_MULTISAMPLE_ARRAY
|| texture_gl
->target
== GL_TEXTURE_2D_MULTISAMPLE
)
4314 texture_gl
->t
.flags
&= ~WINED3D_TEXTURE_DOWNLOADABLE
;
4319 HRESULT CDECL
wined3d_texture_create(struct wined3d_device
*device
, const struct wined3d_resource_desc
*desc
,
4320 UINT layer_count
, UINT level_count
, DWORD flags
, const struct wined3d_sub_resource_data
*data
,
4321 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
4323 unsigned int sub_count
= level_count
* layer_count
;
4327 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, data %p, "
4328 "parent %p, parent_ops %p, texture %p.\n",
4329 device
, desc
, layer_count
, level_count
, flags
, data
, parent
, parent_ops
, texture
);
4333 WARN("Invalid layer count.\n");
4334 return E_INVALIDARG
;
4336 if ((desc
->usage
& WINED3DUSAGE_LEGACY_CUBEMAP
) && layer_count
!= 6)
4338 ERR("Invalid layer count %u for legacy cubemap.\n", layer_count
);
4344 WARN("Invalid level count.\n");
4345 return WINED3DERR_INVALIDCALL
;
4348 if (desc
->multisample_type
!= WINED3D_MULTISAMPLE_NONE
)
4350 const struct wined3d_format
*format
= wined3d_get_format(device
->adapter
, desc
->format
, desc
->bind_flags
);
4352 if (desc
->multisample_type
== WINED3D_MULTISAMPLE_NON_MASKABLE
4353 && desc
->multisample_quality
>= wined3d_popcount(format
->multisample_types
))
4355 WARN("Unsupported quality level %u requested for WINED3D_MULTISAMPLE_NON_MASKABLE.\n",
4356 desc
->multisample_quality
);
4357 return WINED3DERR_NOTAVAILABLE
;
4359 if (desc
->multisample_type
!= WINED3D_MULTISAMPLE_NON_MASKABLE
4360 && (!(format
->multisample_types
& 1u << (desc
->multisample_type
- 1))
4361 || (desc
->multisample_quality
&& desc
->multisample_quality
!= WINED3D_STANDARD_MULTISAMPLE_PATTERN
)))
4363 WARN("Unsupported multisample type %u quality %u requested.\n", desc
->multisample_type
,
4364 desc
->multisample_quality
);
4365 return WINED3DERR_NOTAVAILABLE
;
4371 for (i
= 0; i
< sub_count
; ++i
)
4376 WARN("Invalid sub-resource data specified for sub-resource %u.\n", i
);
4377 return E_INVALIDARG
;
4381 if (FAILED(hr
= device
->adapter
->adapter_ops
->adapter_create_texture(device
, desc
,
4382 layer_count
, level_count
, flags
, parent
, parent_ops
, texture
)))
4385 /* FIXME: We'd like to avoid ever allocating system memory for the texture
4389 struct wined3d_box box
;
4391 for (i
= 0; i
< sub_count
; ++i
)
4393 wined3d_texture_get_level_box(*texture
, i
% (*texture
)->level_count
, &box
);
4394 device
->cs
->c
.ops
->update_sub_resource(&device
->cs
->c
, &(*texture
)->resource
,
4395 i
, &box
, data
[i
].data
, data
[i
].row_pitch
, data
[i
].slice_pitch
);
4399 TRACE("Created texture %p.\n", *texture
);
4404 HRESULT CDECL
wined3d_texture_get_dc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
, HDC
*dc
)
4406 struct wined3d_device
*device
= texture
->resource
.device
;
4407 struct wined3d_texture_sub_resource
*sub_resource
;
4408 struct wined3d_dc_info
*dc_info
;
4410 TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture
, sub_resource_idx
, dc
);
4412 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC
))
4414 WARN("Texture does not support GetDC\n");
4415 /* Don't touch the DC */
4416 return WINED3DERR_INVALIDCALL
;
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
->resource
.map_count
&& !(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4429 return WINED3DERR_INVALIDCALL
;
4431 if (!(dc_info
= texture
->dc_info
) || !dc_info
[sub_resource_idx
].dc
)
4433 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
4435 wined3d_cs_init_object(device
->cs
, wined3d_texture_create_dc
, &texture_idx
);
4436 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
4437 if (!(dc_info
= texture
->dc_info
) || !dc_info
[sub_resource_idx
].dc
)
4438 return WINED3DERR_INVALIDCALL
;
4441 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4442 texture
->flags
|= WINED3D_TEXTURE_DC_IN_USE
;
4443 ++texture
->resource
.map_count
;
4444 ++sub_resource
->map_count
;
4446 *dc
= dc_info
[sub_resource_idx
].dc
;
4447 TRACE("Returning dc %p.\n", *dc
);
4452 HRESULT CDECL
wined3d_texture_release_dc(struct wined3d_texture
*texture
, unsigned int sub_resource_idx
, HDC dc
)
4454 struct wined3d_device
*device
= texture
->resource
.device
;
4455 struct wined3d_texture_sub_resource
*sub_resource
;
4456 struct wined3d_dc_info
*dc_info
;
4458 TRACE("texture %p, sub_resource_idx %u, dc %p.\n", texture
, sub_resource_idx
, dc
);
4460 if (!(sub_resource
= wined3d_texture_get_sub_resource(texture
, sub_resource_idx
)))
4461 return WINED3DERR_INVALIDCALL
;
4463 if (texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_2D
)
4465 WARN("Not supported on %s resources.\n", debug_d3dresourcetype(texture
->resource
.type
));
4466 return WINED3DERR_INVALIDCALL
;
4469 if (!(texture
->flags
& (WINED3D_TEXTURE_GET_DC_LENIENT
| WINED3D_TEXTURE_DC_IN_USE
)))
4470 return WINED3DERR_INVALIDCALL
;
4472 if (!(dc_info
= texture
->dc_info
) || dc_info
[sub_resource_idx
].dc
!= dc
)
4474 WARN("Application tries to release invalid DC %p, sub-resource DC is %p.\n",
4475 dc
, dc_info
? dc_info
[sub_resource_idx
].dc
: NULL
);
4476 return WINED3DERR_INVALIDCALL
;
4479 if (!(texture
->resource
.usage
& WINED3DUSAGE_OWNDC
))
4481 struct wined3d_texture_idx texture_idx
= {texture
, sub_resource_idx
};
4483 wined3d_cs_destroy_object(device
->cs
, wined3d_texture_destroy_dc
, &texture_idx
);
4484 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
4487 --sub_resource
->map_count
;
4488 if (!--texture
->resource
.map_count
&& texture
->update_map_binding
)
4489 wined3d_texture_update_map_binding(texture
);
4490 if (!(texture
->flags
& WINED3D_TEXTURE_GET_DC_LENIENT
))
4491 texture
->flags
&= ~WINED3D_TEXTURE_DC_IN_USE
;
4496 void wined3d_texture_upload_from_texture(struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4497 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
, struct wined3d_texture
*src_texture
,
4498 unsigned int src_sub_resource_idx
, const struct wined3d_box
*src_box
)
4500 unsigned int src_row_pitch
, src_slice_pitch
;
4501 unsigned int update_w
, update_h
, update_d
;
4502 unsigned int src_level
, dst_level
;
4503 struct wined3d_context
*context
;
4504 struct wined3d_bo_address data
;
4506 TRACE("dst_texture %p, dst_sub_resource_idx %u, dst_x %u, dst_y %u, dst_z %u, "
4507 "src_texture %p, src_sub_resource_idx %u, src_box %s.\n",
4508 dst_texture
, dst_sub_resource_idx
, dst_x
, dst_y
, dst_z
,
4509 src_texture
, src_sub_resource_idx
, debug_box(src_box
));
4511 context
= context_acquire(dst_texture
->resource
.device
, NULL
, 0);
4513 /* Only load the sub-resource for partial updates. For newly allocated
4514 * textures the texture wouldn't be the current location, and we'd upload
4515 * zeroes just to overwrite them again. */
4516 update_w
= src_box
->right
- src_box
->left
;
4517 update_h
= src_box
->bottom
- src_box
->top
;
4518 update_d
= src_box
->back
- src_box
->front
;
4519 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4520 if (update_w
== wined3d_texture_get_level_width(dst_texture
, dst_level
)
4521 && update_h
== wined3d_texture_get_level_height(dst_texture
, dst_level
)
4522 && update_d
== wined3d_texture_get_level_depth(dst_texture
, dst_level
))
4523 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
4525 wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
);
4527 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4528 wined3d_texture_get_memory(src_texture
, src_sub_resource_idx
, &data
,
4529 src_texture
->sub_resources
[src_sub_resource_idx
].locations
);
4530 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
4532 dst_texture
->texture_ops
->texture_upload_data(context
, wined3d_const_bo_address(&data
),
4533 src_texture
->resource
.format
, src_box
, src_row_pitch
, src_slice_pitch
, dst_texture
,
4534 dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
, dst_x
, dst_y
, dst_z
);
4536 context_release(context
);
4538 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
4539 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
4542 /* Partial downloads are not supported. */
4543 void wined3d_texture_download_from_texture(struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
,
4544 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
)
4546 unsigned int src_level
, dst_level
, dst_row_pitch
, dst_slice_pitch
;
4547 unsigned int dst_location
= dst_texture
->resource
.map_binding
;
4548 struct wined3d_context
*context
;
4549 struct wined3d_bo_address data
;
4550 struct wined3d_box src_box
;
4551 unsigned int src_location
;
4553 context
= context_acquire(src_texture
->resource
.device
, NULL
, 0);
4555 wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
);
4556 wined3d_texture_get_memory(dst_texture
, dst_sub_resource_idx
, &data
, dst_location
);
4558 if (src_texture
->sub_resources
[src_sub_resource_idx
].locations
& WINED3D_LOCATION_TEXTURE_RGB
)
4559 src_location
= WINED3D_LOCATION_TEXTURE_RGB
;
4561 src_location
= WINED3D_LOCATION_TEXTURE_SRGB
;
4562 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4563 wined3d_texture_get_level_box(src_texture
, src_level
, &src_box
);
4565 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4566 wined3d_texture_get_pitch(dst_texture
, dst_level
, &dst_row_pitch
, &dst_slice_pitch
);
4568 src_texture
->texture_ops
->texture_download_data(context
, src_texture
, src_sub_resource_idx
, src_location
,
4569 &src_box
, &data
, dst_texture
->resource
.format
, 0, 0, 0, dst_row_pitch
, dst_slice_pitch
);
4571 context_release(context
);
4573 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, dst_location
);
4574 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~dst_location
);
4577 static void wined3d_texture_no3d_upload_data(struct wined3d_context
*context
,
4578 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
4579 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
4580 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
4581 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
4583 FIXME("Not implemented.\n");
4586 static void wined3d_texture_no3d_download_data(struct wined3d_context
*context
,
4587 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
4588 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
4589 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
4590 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
4592 FIXME("Not implemented.\n");
4595 static BOOL
wined3d_texture_no3d_prepare_location(struct wined3d_texture
*texture
,
4596 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
4598 if (location
== WINED3D_LOCATION_SYSMEM
)
4599 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
4600 : wined3d_resource_prepare_sysmem(&texture
->resource
);
4602 FIXME("Unhandled location %s.\n", wined3d_debug_location(location
));
4606 static BOOL
wined3d_texture_no3d_load_location(struct wined3d_texture
*texture
,
4607 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
4609 TRACE("texture %p, sub_resource_idx %u, context %p, location %s.\n",
4610 texture
, sub_resource_idx
, context
, wined3d_debug_location(location
));
4612 if (location
== WINED3D_LOCATION_SYSMEM
)
4615 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
4620 static void wined3d_texture_no3d_unload_location(struct wined3d_texture
*texture
,
4621 struct wined3d_context
*context
, unsigned int location
)
4623 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
4626 static const struct wined3d_texture_ops wined3d_texture_no3d_ops
=
4628 wined3d_texture_no3d_prepare_location
,
4629 wined3d_texture_no3d_load_location
,
4630 wined3d_texture_no3d_unload_location
,
4631 wined3d_texture_no3d_upload_data
,
4632 wined3d_texture_no3d_download_data
,
4635 HRESULT
wined3d_texture_no3d_init(struct wined3d_texture
*texture_no3d
, struct wined3d_device
*device
,
4636 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
4637 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
4639 TRACE("texture_no3d %p, device %p, desc %p, layer_count %u, "
4640 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
4641 texture_no3d
, device
, desc
, layer_count
,
4642 level_count
, flags
, parent
, parent_ops
);
4644 return wined3d_texture_init(texture_no3d
, desc
, layer_count
, level_count
,
4645 flags
, device
, parent
, parent_ops
, &texture_no3d
[1], &wined3d_texture_no3d_ops
);
4648 void wined3d_vk_swizzle_from_color_fixup(VkComponentMapping
*mapping
, struct color_fixup_desc fixup
)
4650 static const VkComponentSwizzle swizzle_source
[] =
4652 VK_COMPONENT_SWIZZLE_ZERO
, /* CHANNEL_SOURCE_ZERO */
4653 VK_COMPONENT_SWIZZLE_ONE
, /* CHANNEL_SOURCE_ONE */
4654 VK_COMPONENT_SWIZZLE_R
, /* CHANNEL_SOURCE_X */
4655 VK_COMPONENT_SWIZZLE_G
, /* CHANNEL_SOURCE_Y */
4656 VK_COMPONENT_SWIZZLE_B
, /* CHANNEL_SOURCE_Z */
4657 VK_COMPONENT_SWIZZLE_A
, /* CHANNEL_SOURCE_W */
4660 mapping
->r
= swizzle_source
[fixup
.x_source
];
4661 mapping
->g
= swizzle_source
[fixup
.y_source
];
4662 mapping
->b
= swizzle_source
[fixup
.z_source
];
4663 mapping
->a
= swizzle_source
[fixup
.w_source
];
4666 const VkDescriptorImageInfo
*wined3d_texture_vk_get_default_image_info(struct wined3d_texture_vk
*texture_vk
,
4667 struct wined3d_context_vk
*context_vk
)
4669 const struct wined3d_format_vk
*format_vk
;
4670 const struct wined3d_vk_info
*vk_info
;
4671 struct wined3d_device_vk
*device_vk
;
4672 VkImageViewCreateInfo create_info
;
4673 struct color_fixup_desc fixup
;
4677 if (texture_vk
->default_image_info
.imageView
)
4678 return &texture_vk
->default_image_info
;
4680 format_vk
= wined3d_format_vk(texture_vk
->t
.resource
.format
);
4681 device_vk
= wined3d_device_vk(texture_vk
->t
.resource
.device
);
4682 vk_info
= context_vk
->vk_info
;
4684 if (texture_vk
->t
.layer_count
> 1)
4685 flags
|= WINED3D_VIEW_TEXTURE_ARRAY
;
4687 wined3d_texture_vk_prepare_texture(texture_vk
, context_vk
);
4688 create_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
;
4689 create_info
.pNext
= NULL
;
4690 create_info
.flags
= 0;
4691 create_info
.image
= texture_vk
->image
.vk_image
;
4692 create_info
.viewType
= vk_image_view_type_from_wined3d(texture_vk
->t
.resource
.type
, flags
);
4693 create_info
.format
= format_vk
->vk_format
;
4694 fixup
= format_vk
->f
.color_fixup
;
4695 if (is_identity_fixup(fixup
) || !can_use_texture_swizzle(context_vk
->c
.d3d_info
, &format_vk
->f
))
4697 create_info
.components
.r
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4698 create_info
.components
.g
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4699 create_info
.components
.b
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4700 create_info
.components
.a
= VK_COMPONENT_SWIZZLE_IDENTITY
;
4704 wined3d_vk_swizzle_from_color_fixup(&create_info
.components
, fixup
);
4706 create_info
.subresourceRange
.aspectMask
= vk_aspect_mask_from_format(&format_vk
->f
);
4707 create_info
.subresourceRange
.baseMipLevel
= 0;
4708 create_info
.subresourceRange
.levelCount
= texture_vk
->t
.level_count
;
4709 create_info
.subresourceRange
.baseArrayLayer
= 0;
4710 create_info
.subresourceRange
.layerCount
= texture_vk
->t
.layer_count
;
4711 if ((vr
= VK_CALL(vkCreateImageView(device_vk
->vk_device
, &create_info
,
4712 NULL
, &texture_vk
->default_image_info
.imageView
))) < 0)
4714 ERR("Failed to create Vulkan image view, vr %s.\n", wined3d_debug_vkresult(vr
));
4718 TRACE("Created image view 0x%s.\n", wine_dbgstr_longlong(texture_vk
->default_image_info
.imageView
));
4720 texture_vk
->default_image_info
.sampler
= VK_NULL_HANDLE
;
4721 texture_vk
->default_image_info
.imageLayout
= texture_vk
->layout
;
4723 return &texture_vk
->default_image_info
;
4726 static void wined3d_texture_vk_upload_data(struct wined3d_context
*context
,
4727 const struct wined3d_const_bo_address
*src_bo_addr
, const struct wined3d_format
*src_format
,
4728 const struct wined3d_box
*src_box
, unsigned int src_row_pitch
, unsigned int src_slice_pitch
,
4729 struct wined3d_texture
*dst_texture
, unsigned int dst_sub_resource_idx
, unsigned int dst_location
,
4730 unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
)
4732 struct wined3d_texture_vk
*dst_texture_vk
= wined3d_texture_vk(dst_texture
);
4733 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
4734 unsigned int dst_level
, dst_row_pitch
, dst_slice_pitch
;
4735 struct wined3d_texture_sub_resource
*sub_resource
;
4736 struct wined3d_bo_address staging_bo_addr
;
4737 const struct wined3d_vk_info
*vk_info
;
4738 VkCommandBuffer vk_command_buffer
;
4739 VkImageSubresourceRange vk_range
;
4740 struct wined3d_bo_vk staging_bo
;
4741 VkImageAspectFlags aspect_mask
;
4742 struct wined3d_range range
;
4743 VkBufferImageCopy region
;
4747 TRACE("context %p, src_bo_addr %s, src_format %s, src_box %s, src_row_pitch %u, src_slice_pitch %u, "
4748 "dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_x %u, dst_y %u, dst_z %u.\n",
4749 context
, debug_const_bo_address(src_bo_addr
), debug_d3dformat(src_format
->id
), debug_box(src_box
),
4750 src_row_pitch
, src_slice_pitch
, dst_texture
, dst_sub_resource_idx
,
4751 wined3d_debug_location(dst_location
), dst_x
, dst_y
, dst_z
);
4753 if (src_bo_addr
->buffer_object
)
4755 FIXME("Unhandled buffer object %#lx.\n", src_bo_addr
->buffer_object
);
4759 if (src_format
->id
!= dst_texture
->resource
.format
->id
)
4761 FIXME("Unhandled format conversion (%s -> %s).\n",
4762 debug_d3dformat(src_format
->id
),
4763 debug_d3dformat(dst_texture
->resource
.format
->id
));
4767 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
4768 wined3d_texture_get_pitch(dst_texture
, dst_level
, &dst_row_pitch
, &dst_slice_pitch
);
4769 if (dst_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_1D
)
4770 src_row_pitch
= dst_row_pitch
= 0;
4771 if (dst_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_3D
)
4772 src_slice_pitch
= dst_slice_pitch
= 0;
4774 if (dst_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
4776 FIXME("Unhandled location %s.\n", wined3d_debug_location(dst_location
));
4780 if (wined3d_resource_get_sample_count(&dst_texture_vk
->t
.resource
) > 1)
4782 FIXME("Not supported for multisample textures.\n");
4786 aspect_mask
= vk_aspect_mask_from_format(dst_texture
->resource
.format
);
4787 if (wined3d_popcount(aspect_mask
) > 1)
4789 FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(dst_texture
->resource
.format
->id
));
4793 sub_resource
= &dst_texture_vk
->t
.sub_resources
[dst_sub_resource_idx
];
4794 vk_info
= context_vk
->vk_info
;
4796 src_offset
= src_box
->front
* src_slice_pitch
4797 + (src_box
->top
/ src_format
->block_height
) * src_row_pitch
4798 + (src_box
->left
/ src_format
->block_width
) * src_format
->block_byte_count
;
4800 if (!wined3d_context_vk_create_bo(context_vk
, sub_resource
->size
,
4801 VK_BUFFER_USAGE_TRANSFER_SRC_BIT
, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
))
4803 ERR("Failed to create staging bo.\n");
4807 staging_bo_addr
.buffer_object
= (uintptr_t)&staging_bo
;
4808 staging_bo_addr
.addr
= NULL
;
4809 if (!(map_ptr
= wined3d_context_map_bo_address(context
, &staging_bo_addr
,
4810 sub_resource
->size
, WINED3D_MAP_DISCARD
| WINED3D_MAP_WRITE
)))
4812 ERR("Failed to map staging bo.\n");
4813 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4817 wined3d_format_copy_data(src_format
, src_bo_addr
->addr
+ src_offset
, src_row_pitch
,
4818 src_slice_pitch
, map_ptr
, dst_row_pitch
, dst_slice_pitch
, src_box
->right
- src_box
->left
,
4819 src_box
->bottom
- src_box
->top
, src_box
->back
- src_box
->front
);
4822 range
.size
= sub_resource
->size
;
4823 wined3d_context_unmap_bo_address(context
, &staging_bo_addr
, 1, &range
);
4825 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
4827 ERR("Failed to get command buffer.\n");
4828 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4832 vk_range
.aspectMask
= aspect_mask
;
4833 vk_range
.baseMipLevel
= dst_level
;
4834 vk_range
.levelCount
= 1;
4835 vk_range
.baseArrayLayer
= dst_sub_resource_idx
/ dst_texture_vk
->t
.level_count
;
4836 vk_range
.layerCount
= 1;
4838 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4839 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
4840 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
4841 VK_ACCESS_TRANSFER_WRITE_BIT
,
4842 dst_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
4843 dst_texture_vk
->image
.vk_image
, &vk_range
);
4845 region
.bufferOffset
= staging_bo
.buffer_offset
;
4846 region
.bufferRowLength
= (dst_row_pitch
/ src_format
->block_byte_count
) * src_format
->block_width
;
4848 region
.bufferImageHeight
= (dst_slice_pitch
/ dst_row_pitch
) * src_format
->block_height
;
4850 region
.bufferImageHeight
= 1;
4851 region
.imageSubresource
.aspectMask
= vk_range
.aspectMask
;
4852 region
.imageSubresource
.mipLevel
= vk_range
.baseMipLevel
;
4853 region
.imageSubresource
.baseArrayLayer
= vk_range
.baseArrayLayer
;
4854 region
.imageSubresource
.layerCount
= vk_range
.layerCount
;
4855 region
.imageOffset
.x
= dst_x
;
4856 region
.imageOffset
.y
= dst_y
;
4857 region
.imageOffset
.z
= dst_z
;
4858 region
.imageExtent
.width
= src_box
->right
- src_box
->left
;
4859 region
.imageExtent
.height
= src_box
->bottom
- src_box
->top
;
4860 region
.imageExtent
.depth
= src_box
->back
- src_box
->front
;
4862 VK_CALL(vkCmdCopyBufferToImage(vk_command_buffer
, staging_bo
.vk_buffer
,
4863 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ®ion
));
4865 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4866 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
4867 VK_ACCESS_TRANSFER_WRITE_BIT
,
4868 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
4869 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
4870 dst_texture_vk
->image
.vk_image
, &vk_range
);
4871 wined3d_context_vk_reference_texture(context_vk
, dst_texture_vk
);
4872 wined3d_context_vk_reference_bo(context_vk
, &staging_bo
);
4873 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
4876 static void wined3d_texture_vk_download_data(struct wined3d_context
*context
,
4877 struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
, unsigned int src_location
,
4878 const struct wined3d_box
*src_box
, const struct wined3d_bo_address
*dst_bo_addr
,
4879 const struct wined3d_format
*dst_format
, unsigned int dst_x
, unsigned int dst_y
, unsigned int dst_z
,
4880 unsigned int dst_row_pitch
, unsigned int dst_slice_pitch
)
4882 struct wined3d_texture_vk
*src_texture_vk
= wined3d_texture_vk(src_texture
);
4883 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
4884 unsigned int src_level
, src_width
, src_height
, src_depth
;
4885 struct wined3d_texture_sub_resource
*sub_resource
;
4886 unsigned int src_row_pitch
, src_slice_pitch
;
4887 struct wined3d_bo_address staging_bo_addr
;
4888 const struct wined3d_vk_info
*vk_info
;
4889 VkCommandBuffer vk_command_buffer
;
4890 VkImageSubresourceRange vk_range
;
4891 struct wined3d_bo_vk staging_bo
;
4892 VkImageAspectFlags aspect_mask
;
4893 VkBufferImageCopy region
;
4896 TRACE("context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_box %s, dst_bo_addr %s, "
4897 "dst_format %s, dst_x %u, dst_y %u, dst_z %u, dst_row_pitch %u, dst_slice_pitch %u.\n",
4898 context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
4899 debug_box(src_box
), debug_bo_address(dst_bo_addr
), debug_d3dformat(dst_format
->id
),
4900 dst_x
, dst_y
, dst_z
, dst_row_pitch
, dst_slice_pitch
);
4902 if (src_location
!= WINED3D_LOCATION_TEXTURE_RGB
)
4904 FIXME("Unhandled location %s.\n", wined3d_debug_location(src_location
));
4908 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
4909 src_width
= wined3d_texture_get_level_width(src_texture
, src_level
);
4910 src_height
= wined3d_texture_get_level_height(src_texture
, src_level
);
4911 src_depth
= wined3d_texture_get_level_depth(src_texture
, src_level
);
4912 if (src_box
->left
|| src_box
->top
|| src_box
->right
!= src_width
|| src_box
->bottom
!= src_height
4913 || src_box
->front
|| src_box
->back
!= src_depth
)
4915 FIXME("Unhandled source box %s.\n", debug_box(src_box
));
4919 if (dst_bo_addr
->buffer_object
)
4921 FIXME("Unhandled buffer object %#lx.\n", dst_bo_addr
->buffer_object
);
4925 if (dst_format
->id
!= src_texture
->resource
.format
->id
)
4927 FIXME("Unhandled format conversion (%s -> %s).\n",
4928 debug_d3dformat(src_texture
->resource
.format
->id
),
4929 debug_d3dformat(dst_format
->id
));
4933 if (dst_x
|| dst_y
|| dst_z
)
4935 FIXME("Unhandled destination (%u, %u, %u).\n", dst_x
, dst_y
, dst_z
);
4939 if (wined3d_resource_get_sample_count(&src_texture_vk
->t
.resource
) > 1)
4941 FIXME("Not supported for multisample textures.\n");
4945 aspect_mask
= vk_aspect_mask_from_format(src_texture
->resource
.format
);
4946 if (wined3d_popcount(aspect_mask
) > 1)
4948 FIXME("Unhandled multi-aspect format %s.\n", debug_d3dformat(src_texture
->resource
.format
->id
));
4952 wined3d_texture_get_pitch(src_texture
, src_level
, &src_row_pitch
, &src_slice_pitch
);
4953 if (src_texture
->resource
.type
== WINED3D_RTYPE_TEXTURE_1D
)
4954 src_row_pitch
= dst_row_pitch
= 0;
4955 if (src_texture
->resource
.type
!= WINED3D_RTYPE_TEXTURE_3D
)
4956 src_slice_pitch
= dst_slice_pitch
= 0;
4958 sub_resource
= &src_texture_vk
->t
.sub_resources
[src_sub_resource_idx
];
4959 vk_info
= context_vk
->vk_info
;
4960 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
4962 ERR("Failed to get command buffer.\n");
4966 if (!wined3d_context_vk_create_bo(context_vk
, sub_resource
->size
,
4967 VK_BUFFER_USAGE_TRANSFER_DST_BIT
, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
))
4969 ERR("Failed to create staging bo.\n");
4973 vk_range
.aspectMask
= aspect_mask
;
4974 vk_range
.baseMipLevel
= src_level
;
4975 vk_range
.levelCount
= 1;
4976 vk_range
.baseArrayLayer
= src_sub_resource_idx
/ src_texture_vk
->t
.level_count
;
4977 vk_range
.layerCount
= 1;
4979 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
4980 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
4981 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
4982 VK_ACCESS_TRANSFER_READ_BIT
,
4983 src_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
4984 src_texture_vk
->image
.vk_image
, &vk_range
);
4986 region
.bufferOffset
= staging_bo
.buffer_offset
;
4987 region
.bufferRowLength
= 0;
4988 region
.bufferImageHeight
= 0;
4989 region
.imageSubresource
.aspectMask
= vk_range
.aspectMask
;
4990 region
.imageSubresource
.mipLevel
= vk_range
.baseMipLevel
;
4991 region
.imageSubresource
.baseArrayLayer
= vk_range
.baseArrayLayer
;
4992 region
.imageSubresource
.layerCount
= vk_range
.layerCount
;
4993 region
.imageOffset
.x
= 0;
4994 region
.imageOffset
.y
= 0;
4995 region
.imageOffset
.z
= 0;
4996 region
.imageExtent
.width
= src_width
;
4997 region
.imageExtent
.height
= src_height
;
4998 region
.imageExtent
.depth
= src_depth
;
5000 VK_CALL(vkCmdCopyImageToBuffer(vk_command_buffer
, src_texture_vk
->image
.vk_image
,
5001 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, staging_bo
.vk_buffer
, 1, ®ion
));
5003 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
5004 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
5005 VK_ACCESS_TRANSFER_READ_BIT
,
5006 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
5007 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
5008 src_texture_vk
->image
.vk_image
, &vk_range
);
5010 wined3d_context_vk_reference_texture(context_vk
, src_texture_vk
);
5011 wined3d_context_vk_reference_bo(context_vk
, &staging_bo
);
5012 wined3d_context_vk_submit_command_buffer(context_vk
, 0, NULL
, NULL
, 0, NULL
);
5013 wined3d_context_vk_wait_command_buffer(context_vk
, src_texture_vk
->image
.command_buffer_id
);
5015 staging_bo_addr
.buffer_object
= (uintptr_t)&staging_bo
;
5016 staging_bo_addr
.addr
= (uint8_t *)NULL
;
5017 if (!(map_ptr
= wined3d_context_map_bo_address(context
, &staging_bo_addr
,
5018 sub_resource
->size
, WINED3D_MAP_READ
)))
5020 ERR("Failed to map staging bo.\n");
5021 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
5025 wined3d_format_copy_data(dst_format
, map_ptr
, src_row_pitch
, src_slice_pitch
,
5026 dst_bo_addr
->addr
, dst_row_pitch
, dst_slice_pitch
, src_box
->right
- src_box
->left
,
5027 src_box
->bottom
- src_box
->top
, src_box
->back
- src_box
->front
);
5029 wined3d_context_unmap_bo_address(context
, &staging_bo_addr
, 0, NULL
);
5030 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
5033 static BOOL
wined3d_texture_vk_load_texture(struct wined3d_texture_vk
*texture_vk
,
5034 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
5036 struct wined3d_texture_sub_resource
*sub_resource
;
5037 unsigned int level
, row_pitch
, slice_pitch
;
5038 struct wined3d_bo_address data
;
5039 struct wined3d_box src_box
;
5041 sub_resource
= &texture_vk
->t
.sub_resources
[sub_resource_idx
];
5042 if (!(sub_resource
->locations
& WINED3D_LOCATION_SYSMEM
))
5044 ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource
->locations
));
5048 level
= sub_resource_idx
% texture_vk
->t
.level_count
;
5049 wined3d_texture_get_memory(&texture_vk
->t
, sub_resource_idx
, &data
, WINED3D_LOCATION_SYSMEM
);
5050 wined3d_texture_get_level_box(&texture_vk
->t
, level
, &src_box
);
5051 wined3d_texture_get_pitch(&texture_vk
->t
, level
, &row_pitch
, &slice_pitch
);
5052 wined3d_texture_vk_upload_data(context
, wined3d_const_bo_address(&data
), texture_vk
->t
.resource
.format
,
5053 &src_box
, row_pitch
, slice_pitch
, &texture_vk
->t
, sub_resource_idx
,
5054 WINED3D_LOCATION_TEXTURE_RGB
, 0, 0, 0);
5059 static BOOL
wined3d_texture_vk_load_sysmem(struct wined3d_texture_vk
*texture_vk
,
5060 unsigned int sub_resource_idx
, struct wined3d_context
*context
)
5062 struct wined3d_texture_sub_resource
*sub_resource
;
5063 unsigned int level
, row_pitch
, slice_pitch
;
5064 struct wined3d_bo_address data
;
5065 struct wined3d_box src_box
;
5067 sub_resource
= &texture_vk
->t
.sub_resources
[sub_resource_idx
];
5068 if (!(sub_resource
->locations
& WINED3D_LOCATION_TEXTURE_RGB
))
5070 ERR("Unimplemented load from %s.\n", wined3d_debug_location(sub_resource
->locations
));
5074 level
= sub_resource_idx
% texture_vk
->t
.level_count
;
5075 wined3d_texture_get_memory(&texture_vk
->t
, sub_resource_idx
, &data
, WINED3D_LOCATION_SYSMEM
);
5076 wined3d_texture_get_level_box(&texture_vk
->t
, level
, &src_box
);
5077 wined3d_texture_get_pitch(&texture_vk
->t
, level
, &row_pitch
, &slice_pitch
);
5078 wined3d_texture_vk_download_data(context
, &texture_vk
->t
, sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
,
5079 &src_box
, &data
, texture_vk
->t
.resource
.format
, 0, 0, 0, row_pitch
, slice_pitch
);
5084 BOOL
wined3d_texture_vk_prepare_texture(struct wined3d_texture_vk
*texture_vk
,
5085 struct wined3d_context_vk
*context_vk
)
5087 const struct wined3d_format_vk
*format_vk
;
5088 struct wined3d_resource
*resource
;
5089 VkCommandBuffer vk_command_buffer
;
5090 VkImageSubresourceRange vk_range
;
5091 VkImageUsageFlags vk_usage
;
5092 VkImageType vk_image_type
;
5093 unsigned int flags
= 0;
5095 if (texture_vk
->t
.flags
& WINED3D_TEXTURE_RGB_ALLOCATED
)
5098 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
5100 ERR("Failed to get command buffer.\n");
5104 resource
= &texture_vk
->t
.resource
;
5105 format_vk
= wined3d_format_vk(resource
->format
);
5107 if (wined3d_format_is_typeless(&format_vk
->f
) || texture_vk
->t
.swapchain
)
5108 flags
|= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT
;
5110 switch (resource
->type
)
5112 case WINED3D_RTYPE_TEXTURE_1D
:
5113 vk_image_type
= VK_IMAGE_TYPE_1D
;
5115 case WINED3D_RTYPE_TEXTURE_2D
:
5116 vk_image_type
= VK_IMAGE_TYPE_2D
;
5117 if (texture_vk
->t
.layer_count
>= 6 && resource
->width
== resource
->height
)
5118 flags
|= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT
;
5120 case WINED3D_RTYPE_TEXTURE_3D
:
5121 vk_image_type
= VK_IMAGE_TYPE_3D
;
5122 if (resource
->bind_flags
& (WINED3D_BIND_RENDER_TARGET
| WINED3D_BIND_UNORDERED_ACCESS
))
5123 flags
|= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT
;
5126 ERR("Invalid resource type %s.\n", debug_d3dresourcetype(resource
->type
));
5127 vk_image_type
= VK_IMAGE_TYPE_2D
;
5131 vk_usage
= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
| VK_IMAGE_USAGE_TRANSFER_DST_BIT
;
5132 if (resource
->bind_flags
& WINED3D_BIND_SHADER_RESOURCE
)
5133 vk_usage
|= VK_IMAGE_USAGE_SAMPLED_BIT
;
5134 if (resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)
5135 vk_usage
|= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
5136 if (resource
->bind_flags
& WINED3D_BIND_DEPTH_STENCIL
)
5137 vk_usage
|= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
;
5138 if (resource
->bind_flags
& WINED3D_BIND_UNORDERED_ACCESS
)
5139 vk_usage
|= VK_IMAGE_USAGE_STORAGE_BIT
;
5141 texture_vk
->layout
= VK_IMAGE_LAYOUT_GENERAL
;
5142 if (wined3d_popcount(resource
->bind_flags
== 1))
5144 switch (resource
->bind_flags
)
5146 case WINED3D_BIND_RENDER_TARGET
:
5147 texture_vk
->layout
= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
;
5150 case WINED3D_BIND_DEPTH_STENCIL
:
5151 texture_vk
->layout
= VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
;
5154 case WINED3D_BIND_SHADER_RESOURCE
:
5155 texture_vk
->layout
= VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
;
5163 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, vk_usage
, format_vk
->vk_format
,
5164 resource
->width
, resource
->height
, resource
->depth
, max(1, wined3d_resource_get_sample_count(resource
)),
5165 texture_vk
->t
.level_count
, texture_vk
->t
.layer_count
, flags
, &texture_vk
->image
))
5170 vk_range
.aspectMask
= vk_aspect_mask_from_format(&format_vk
->f
);
5171 vk_range
.baseMipLevel
= 0;
5172 vk_range
.levelCount
= VK_REMAINING_MIP_LEVELS
;
5173 vk_range
.baseArrayLayer
= 0;
5174 vk_range
.layerCount
= VK_REMAINING_ARRAY_LAYERS
;
5176 wined3d_context_vk_reference_texture(context_vk
, texture_vk
);
5177 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
5178 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
,
5180 VK_IMAGE_LAYOUT_UNDEFINED
, texture_vk
->layout
,
5181 texture_vk
->image
.vk_image
, &vk_range
);
5183 texture_vk
->t
.flags
|= WINED3D_TEXTURE_RGB_ALLOCATED
;
5185 TRACE("Created image 0x%s, memory 0x%s for texture %p.\n",
5186 wine_dbgstr_longlong(texture_vk
->image
.vk_image
), wine_dbgstr_longlong(texture_vk
->image
.vk_memory
), texture_vk
);
5191 static BOOL
wined3d_texture_vk_prepare_location(struct wined3d_texture
*texture
,
5192 unsigned int sub_resource_idx
, struct wined3d_context
*context
, unsigned int location
)
5196 case WINED3D_LOCATION_SYSMEM
:
5197 return texture
->sub_resources
[sub_resource_idx
].user_memory
? TRUE
5198 : wined3d_resource_prepare_sysmem(&texture
->resource
);
5200 case WINED3D_LOCATION_TEXTURE_RGB
:
5201 return wined3d_texture_vk_prepare_texture(wined3d_texture_vk(texture
), wined3d_context_vk(context
));
5204 FIXME("Unhandled location %s.\n", wined3d_debug_location(location
));
5209 static BOOL
wined3d_texture_vk_load_location(struct wined3d_texture
*texture
,
5210 unsigned int sub_resource_idx
, struct wined3d_context
*context
, DWORD location
)
5212 if (!wined3d_texture_vk_prepare_location(texture
, sub_resource_idx
, context
, location
))
5217 case WINED3D_LOCATION_TEXTURE_RGB
:
5218 return wined3d_texture_vk_load_texture(wined3d_texture_vk(texture
), sub_resource_idx
, context
);
5220 case WINED3D_LOCATION_SYSMEM
:
5221 return wined3d_texture_vk_load_sysmem(wined3d_texture_vk(texture
), sub_resource_idx
, context
);
5224 FIXME("Unimplemented location %s.\n", wined3d_debug_location(location
));
5229 static void wined3d_texture_vk_unload_location(struct wined3d_texture
*texture
,
5230 struct wined3d_context
*context
, unsigned int location
)
5232 struct wined3d_texture_vk
*texture_vk
= wined3d_texture_vk(texture
);
5233 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
5235 TRACE("texture %p, context %p, location %s.\n", texture
, context
, wined3d_debug_location(location
));
5239 case WINED3D_LOCATION_TEXTURE_RGB
:
5240 if (texture_vk
->default_image_info
.imageView
)
5242 wined3d_context_vk_destroy_vk_image_view(context_vk
,
5243 texture_vk
->default_image_info
.imageView
, texture_vk
->image
.command_buffer_id
);
5244 texture_vk
->default_image_info
.imageView
= VK_NULL_HANDLE
;
5247 if (texture_vk
->image
.vk_image
)
5248 wined3d_context_vk_destroy_image(context_vk
, &texture_vk
->image
);
5251 case WINED3D_LOCATION_BUFFER
:
5252 case WINED3D_LOCATION_TEXTURE_SRGB
:
5253 case WINED3D_LOCATION_RB_MULTISAMPLE
:
5254 case WINED3D_LOCATION_RB_RESOLVED
:
5258 ERR("Unhandled location %s.\n", wined3d_debug_location(location
));
5263 static const struct wined3d_texture_ops wined3d_texture_vk_ops
=
5265 wined3d_texture_vk_prepare_location
,
5266 wined3d_texture_vk_load_location
,
5267 wined3d_texture_vk_unload_location
,
5268 wined3d_texture_vk_upload_data
,
5269 wined3d_texture_vk_download_data
,
5272 HRESULT
wined3d_texture_vk_init(struct wined3d_texture_vk
*texture_vk
, struct wined3d_device
*device
,
5273 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
5274 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
)
5276 TRACE("texture_vk %p, device %p, desc %p, layer_count %u, "
5277 "level_count %u, flags %#x, parent %p, parent_ops %p.\n",
5278 texture_vk
, device
, desc
, layer_count
,
5279 level_count
, flags
, parent
, parent_ops
);
5281 return wined3d_texture_init(&texture_vk
->t
, desc
, layer_count
, level_count
,
5282 flags
, device
, parent
, parent_ops
, &texture_vk
[1], &wined3d_texture_vk_ops
);
5285 void wined3d_texture_vk_barrier(struct wined3d_texture_vk
*texture_vk
,
5286 struct wined3d_context_vk
*context_vk
, uint32_t bind_mask
)
5288 VkImageSubresourceRange vk_range
;
5290 TRACE("texture_vk %p, context_vk %p, bind_mask %s.\n",
5291 texture_vk
, context_vk
, wined3d_debug_bind_flags(bind_mask
));
5293 if (texture_vk
->bind_mask
&& texture_vk
->bind_mask
!= bind_mask
)
5295 TRACE(" %s -> %s.\n",
5296 wined3d_debug_bind_flags(texture_vk
->bind_mask
), wined3d_debug_bind_flags(bind_mask
));
5298 vk_range
.aspectMask
= vk_aspect_mask_from_format(texture_vk
->t
.resource
.format
);
5299 vk_range
.baseMipLevel
= 0;
5300 vk_range
.levelCount
= VK_REMAINING_MIP_LEVELS
;
5301 vk_range
.baseArrayLayer
= 0;
5302 vk_range
.layerCount
= VK_REMAINING_ARRAY_LAYERS
;
5304 wined3d_context_vk_image_barrier(context_vk
, wined3d_context_vk_get_command_buffer(context_vk
),
5305 vk_pipeline_stage_mask_from_bind_flags(texture_vk
->bind_mask
),
5306 vk_pipeline_stage_mask_from_bind_flags(bind_mask
),
5307 vk_access_mask_from_bind_flags(texture_vk
->bind_mask
), vk_access_mask_from_bind_flags(bind_mask
),
5308 texture_vk
->layout
, texture_vk
->layout
, texture_vk
->image
.vk_image
, &vk_range
);
5310 texture_vk
->bind_mask
= bind_mask
;
5313 static void ffp_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
5315 struct wined3d_blitter
*next
;
5317 if ((next
= blitter
->next
))
5318 next
->ops
->blitter_destroy(next
, context
);
5323 static bool ffp_blit_supported(enum wined3d_blit_op blit_op
, const struct wined3d_context
*context
,
5324 const struct wined3d_resource
*src_resource
, DWORD src_location
,
5325 const struct wined3d_resource
*dst_resource
, DWORD dst_location
)
5327 const struct wined3d_format
*src_format
= src_resource
->format
;
5328 const struct wined3d_format
*dst_format
= dst_resource
->format
;
5331 if (src_resource
->type
!= WINED3D_RTYPE_TEXTURE_2D
)
5334 decompress
= (src_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
)
5335 && !(dst_format
->flags
[WINED3D_GL_RES_TYPE_TEX_2D
] & WINED3DFMT_FLAG_COMPRESSED
);
5336 if (!decompress
&& !(src_resource
->access
& dst_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
5338 TRACE("Source or destination resource is not GPU accessible.\n");
5342 if (blit_op
== WINED3D_BLIT_OP_RAW_BLIT
&& dst_format
->id
== src_format
->id
)
5344 if (dst_format
->depth_size
|| dst_format
->stencil_size
)
5345 blit_op
= WINED3D_BLIT_OP_DEPTH_BLIT
;
5347 blit_op
= WINED3D_BLIT_OP_COLOR_BLIT
;
5352 case WINED3D_BLIT_OP_COLOR_BLIT_CKEY
:
5353 if (context
->d3d_info
->shader_color_key
)
5355 TRACE("Colour keying requires converted textures.\n");
5358 case WINED3D_BLIT_OP_COLOR_BLIT
:
5359 case WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
:
5360 if (!wined3d_context_gl_const(context
)->gl_info
->supported
[WINED3D_GL_LEGACY_CONTEXT
])
5365 TRACE("Checking support for fixup:\n");
5366 dump_color_fixup_desc(src_format
->color_fixup
);
5369 /* We only support identity conversions. */
5370 if (!is_identity_fixup(src_format
->color_fixup
)
5371 || !is_identity_fixup(dst_format
->color_fixup
))
5373 if (wined3d_settings
.offscreen_rendering_mode
== ORM_BACKBUFFER
5374 && dst_format
->id
== src_format
->id
&& dst_location
== WINED3D_LOCATION_DRAWABLE
)
5376 WARN("Claiming fixup support because of ORM_BACKBUFFER.\n");
5380 TRACE("Fixups are not supported.\n");
5385 if (!(dst_resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
))
5387 TRACE("Can only blit to render targets.\n");
5393 TRACE("Unsupported blit operation %#x.\n", blit_op
);
5398 static bool is_full_clear(const struct wined3d_rendertarget_view
*rtv
, const RECT
*draw_rect
, const RECT
*clear_rect
)
5400 unsigned int height
= rtv
->height
;
5401 unsigned int width
= rtv
->width
;
5403 /* partial draw rect */
5404 if (draw_rect
->left
|| draw_rect
->top
|| draw_rect
->right
< width
|| draw_rect
->bottom
< height
)
5407 /* partial clear rect */
5408 if (clear_rect
&& (clear_rect
->left
> 0 || clear_rect
->top
> 0
5409 || clear_rect
->right
< width
|| clear_rect
->bottom
< height
))
5415 static void ffp_blitter_clear_rendertargets(struct wined3d_device
*device
, unsigned int rt_count
,
5416 const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rect
, const RECT
*draw_rect
,
5417 uint32_t flags
, const struct wined3d_color
*colour
, float depth
, unsigned int stencil
)
5419 struct wined3d_rendertarget_view
*rtv
= rt_count
? fb
->render_targets
[0] : NULL
;
5420 struct wined3d_rendertarget_view
*dsv
= fb
->depth_stencil
;
5421 const struct wined3d_state
*state
= &device
->cs
->state
;
5422 struct wined3d_texture
*depth_stencil
= NULL
;
5423 unsigned int drawable_width
, drawable_height
;
5424 const struct wined3d_gl_info
*gl_info
;
5425 struct wined3d_context_gl
*context_gl
;
5426 struct wined3d_texture
*target
= NULL
;
5427 struct wined3d_color colour_srgb
;
5428 struct wined3d_context
*context
;
5429 GLbitfield clear_mask
= 0;
5430 bool render_offscreen
;
5433 if (rtv
&& rtv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
5435 target
= texture_from_resource(rtv
->resource
);
5436 context
= context_acquire(device
, target
, rtv
->sub_resource_idx
);
5440 context
= context_acquire(device
, NULL
, 0);
5442 context_gl
= wined3d_context_gl(context
);
5444 if (dsv
&& dsv
->resource
->type
!= WINED3D_RTYPE_BUFFER
)
5445 depth_stencil
= texture_from_resource(dsv
->resource
);
5447 if (!context_gl
->valid
)
5449 context_release(context
);
5450 WARN("Invalid context, skipping clear.\n");
5453 gl_info
= context_gl
->gl_info
;
5455 /* When we're clearing parts of the drawable, make sure that the target
5456 * surface is well up to date in the drawable. After the clear we'll mark
5457 * the drawable up to date, so we have to make sure that this is true for
5458 * the cleared parts, and the untouched parts.
5460 * If we're clearing the whole target there is no need to copy it into the
5461 * drawable, it will be overwritten anyway. If we're not clearing the
5462 * colour buffer we don't have to copy either since we're not going to set
5463 * the drawable up to date. We have to check all settings that limit the
5464 * clear area though. Do not bother checking all this if the destination
5465 * surface is in the drawable anyway. */
5466 for (i
= 0; i
< rt_count
; ++i
)
5468 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
5470 if (rtv
&& rtv
->format
->id
!= WINED3DFMT_NULL
)
5472 if (flags
& WINED3DCLEAR_TARGET
&& !is_full_clear(rtv
, draw_rect
, rect_count
? clear_rect
: NULL
))
5473 wined3d_rendertarget_view_load_location(rtv
, context
, rtv
->resource
->draw_binding
);
5475 wined3d_rendertarget_view_prepare_location(rtv
, context
, rtv
->resource
->draw_binding
);
5481 render_offscreen
= context
->render_offscreen
;
5482 wined3d_rendertarget_view_get_drawable_size(rtv
, context
, &drawable_width
, &drawable_height
);
5486 unsigned int ds_level
= dsv
->sub_resource_idx
% depth_stencil
->level_count
;
5488 render_offscreen
= true;
5489 drawable_width
= wined3d_texture_get_level_pow2_width(depth_stencil
, ds_level
);
5490 drawable_height
= wined3d_texture_get_level_pow2_height(depth_stencil
, ds_level
);
5495 DWORD ds_location
= render_offscreen
? dsv
->resource
->draw_binding
: WINED3D_LOCATION_DRAWABLE
;
5497 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)
5498 && !is_full_clear(dsv
, draw_rect
, rect_count
? clear_rect
: NULL
))
5499 wined3d_rendertarget_view_load_location(dsv
, context
, ds_location
);
5501 wined3d_rendertarget_view_prepare_location(dsv
, context
, ds_location
);
5503 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5505 wined3d_rendertarget_view_validate_location(dsv
, ds_location
);
5506 wined3d_rendertarget_view_invalidate_location(dsv
, ~ds_location
);
5510 if (!wined3d_context_gl_apply_clear_state(context_gl
, state
, rt_count
, fb
))
5512 context_release(context
);
5513 WARN("Failed to apply clear state, skipping clear.\n");
5517 /* Only set the values up once, as they are not changing. */
5518 if (flags
& WINED3DCLEAR_STENCIL
)
5520 if (gl_info
->supported
[EXT_STENCIL_TWO_SIDE
])
5521 gl_info
->gl_ops
.gl
.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT
);
5522 gl_info
->gl_ops
.gl
.p_glStencilMask(~0u);
5523 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
5524 gl_info
->gl_ops
.gl
.p_glClearStencil(stencil
);
5525 checkGLcall("glClearStencil");
5526 clear_mask
= clear_mask
| GL_STENCIL_BUFFER_BIT
;
5529 if (flags
& WINED3DCLEAR_ZBUFFER
)
5531 gl_info
->gl_ops
.gl
.p_glDepthMask(GL_TRUE
);
5532 context_invalidate_state(context
, STATE_DEPTH_STENCIL
);
5533 if (gl_info
->supported
[ARB_ES2_COMPATIBILITY
])
5534 GL_EXTCALL(glClearDepthf(depth
));
5536 gl_info
->gl_ops
.gl
.p_glClearDepth(depth
);
5537 checkGLcall("glClearDepth");
5538 clear_mask
= clear_mask
| GL_DEPTH_BUFFER_BIT
;
5541 if (flags
& WINED3DCLEAR_TARGET
)
5543 for (i
= 0; i
< rt_count
; ++i
)
5545 struct wined3d_rendertarget_view
*rtv
= fb
->render_targets
[i
];
5550 if (rtv
->resource
->type
== WINED3D_RTYPE_BUFFER
)
5552 FIXME("Not supported on buffer resources.\n");
5556 wined3d_rendertarget_view_validate_location(rtv
, rtv
->resource
->draw_binding
);
5557 wined3d_rendertarget_view_invalidate_location(rtv
, ~rtv
->resource
->draw_binding
);
5560 if (!gl_info
->supported
[ARB_FRAMEBUFFER_SRGB
] && needs_srgb_write(context
->d3d_info
, state
, fb
))
5563 WARN("Clearing multiple sRGB render targets without GL_ARB_framebuffer_sRGB "
5564 "support, this might cause graphical issues.\n");
5566 wined3d_colour_srgb_from_linear(&colour_srgb
, colour
);
5567 colour
= &colour_srgb
;
5570 gl_info
->gl_ops
.gl
.p_glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
5571 context_invalidate_state(context
, STATE_BLEND
);
5572 gl_info
->gl_ops
.gl
.p_glClearColor(colour
->r
, colour
->g
, colour
->b
, colour
->a
);
5573 checkGLcall("glClearColor");
5574 clear_mask
= clear_mask
| GL_COLOR_BUFFER_BIT
;
5579 if (render_offscreen
)
5581 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, draw_rect
->top
,
5582 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
5586 gl_info
->gl_ops
.gl
.p_glScissor(draw_rect
->left
, drawable_height
- draw_rect
->bottom
,
5587 draw_rect
->right
- draw_rect
->left
, draw_rect
->bottom
- draw_rect
->top
);
5589 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
5595 /* Now process each rect in turn. */
5596 for (i
= 0; i
< rect_count
; ++i
)
5598 /* Note that GL uses lower left, width/height. */
5599 IntersectRect(¤t_rect
, draw_rect
, &clear_rect
[i
]);
5601 TRACE("clear_rect[%u] %s, current_rect %s.\n", i
,
5602 wine_dbgstr_rect(&clear_rect
[i
]),
5603 wine_dbgstr_rect(¤t_rect
));
5605 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored
5606 * silently. The rectangle is not cleared, no error is returned,
5607 * but further rectangles are still cleared if they are valid. */
5608 if (current_rect
.left
> current_rect
.right
|| current_rect
.top
> current_rect
.bottom
)
5610 TRACE("Rectangle with negative dimensions, ignoring.\n");
5614 if (render_offscreen
)
5616 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, current_rect
.top
,
5617 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
5621 gl_info
->gl_ops
.gl
.p_glScissor(current_rect
.left
, drawable_height
- current_rect
.bottom
,
5622 current_rect
.right
- current_rect
.left
, current_rect
.bottom
- current_rect
.top
);
5624 gl_info
->gl_ops
.gl
.p_glClear(clear_mask
);
5627 context
->scissor_rect_count
= WINED3D_MAX_VIEWPORTS
;
5628 checkGLcall("clear");
5630 if (flags
& WINED3DCLEAR_TARGET
&& target
->swapchain
&& target
->swapchain
->front_buffer
== target
)
5631 gl_info
->gl_ops
.gl
.p_glFlush();
5633 context_release(context
);
5636 static bool blitter_use_cpu_clear(struct wined3d_rendertarget_view
*view
)
5638 struct wined3d_resource
*resource
;
5639 struct wined3d_texture
*texture
;
5642 resource
= view
->resource
;
5643 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
5644 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
);
5646 texture
= texture_from_resource(resource
);
5647 locations
= texture
->sub_resources
[view
->sub_resource_idx
].locations
;
5648 if (locations
& (resource
->map_binding
| WINED3D_LOCATION_DISCARDED
))
5649 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
5650 || (texture
->flags
& WINED3D_TEXTURE_PIN_SYSMEM
);
5652 return !(resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
)
5653 && !(texture
->flags
& WINED3D_TEXTURE_CONVERTED
);
5656 static void ffp_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
5657 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
5658 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
5660 struct wined3d_rendertarget_view
*view
, *previous
= NULL
;
5661 bool have_identical_size
= TRUE
;
5662 struct wined3d_fb_state tmp_fb
;
5663 unsigned int next_rt_count
= 0;
5664 struct wined3d_blitter
*next
;
5665 DWORD next_flags
= 0;
5668 if (flags
& WINED3DCLEAR_TARGET
)
5670 for (i
= 0; i
< rt_count
; ++i
)
5672 if (!(view
= fb
->render_targets
[i
]))
5675 if (blitter_use_cpu_clear(view
)
5676 || (!(view
->resource
->bind_flags
& WINED3D_BIND_RENDER_TARGET
)
5677 && (wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
5678 || !(view
->format_flags
& WINED3DFMT_FLAG_FBO_ATTACHABLE
))))
5680 next_flags
|= WINED3DCLEAR_TARGET
;
5681 flags
&= ~WINED3DCLEAR_TARGET
;
5682 next_rt_count
= rt_count
;
5687 /* FIXME: We should reject colour fills on formats with fixups,
5688 * but this would break P8 colour fills for example. */
5692 if ((flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)) && (view
= fb
->depth_stencil
)
5693 && (!view
->format
->depth_size
|| (flags
& WINED3DCLEAR_ZBUFFER
))
5694 && (!view
->format
->stencil_size
|| (flags
& WINED3DCLEAR_STENCIL
))
5695 && blitter_use_cpu_clear(view
))
5697 next_flags
|= flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
5698 flags
&= ~(WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
5703 for (i
= 0; i
< rt_count
; ++i
)
5705 if (!(view
= fb
->render_targets
[i
]))
5708 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
5709 have_identical_size
= false;
5712 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5714 view
= fb
->depth_stencil
;
5716 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
5717 have_identical_size
= false;
5720 if (have_identical_size
)
5722 ffp_blitter_clear_rendertargets(device
, rt_count
, fb
, rect_count
,
5723 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
5727 for (i
= 0; i
< rt_count
; ++i
)
5729 if (!(view
= fb
->render_targets
[i
]))
5732 tmp_fb
.render_targets
[0] = view
;
5733 tmp_fb
.depth_stencil
= NULL
;
5734 ffp_blitter_clear_rendertargets(device
, 1, &tmp_fb
, rect_count
,
5735 clear_rects
, draw_rect
, WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
5737 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
5739 tmp_fb
.render_targets
[0] = NULL
;
5740 tmp_fb
.depth_stencil
= fb
->depth_stencil
;
5741 ffp_blitter_clear_rendertargets(device
, 0, &tmp_fb
, rect_count
,
5742 clear_rects
, draw_rect
, flags
& ~WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
5747 if (next_flags
&& (next
= blitter
->next
))
5748 next
->ops
->blitter_clear(next
, device
, next_rt_count
, fb
, rect_count
,
5749 clear_rects
, draw_rect
, next_flags
, colour
, depth
, stencil
);
5752 static DWORD
ffp_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
5753 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
5754 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
5755 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
5756 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
5757 const struct wined3d_format
*resolve_format
)
5759 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
5760 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
5761 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
5762 struct wined3d_resource
*src_resource
, *dst_resource
;
5763 struct wined3d_texture
*staging_texture
= NULL
;
5764 struct wined3d_color_key old_blt_key
;
5765 struct wined3d_device
*device
;
5766 struct wined3d_blitter
*next
;
5767 DWORD old_colour_key_flags
;
5770 src_resource
= &src_texture
->resource
;
5771 dst_resource
= &dst_texture
->resource
;
5772 device
= dst_resource
->device
;
5774 if (!ffp_blit_supported(op
, context
, src_resource
, src_location
, dst_resource
, dst_location
))
5776 if ((next
= blitter
->next
))
5777 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
5778 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
5782 TRACE("Blt from texture %p, %u to rendertarget %p, %u.\n",
5783 src_texture
, src_sub_resource_idx
, dst_texture
, dst_sub_resource_idx
);
5785 old_blt_key
= src_texture
->async
.src_blt_color_key
;
5786 old_colour_key_flags
= src_texture
->async
.color_key_flags
;
5787 wined3d_texture_set_color_key(src_texture
, WINED3D_CKEY_SRC_BLT
, colour_key
);
5789 if (!(src_texture
->resource
.access
& WINED3D_RESOURCE_ACCESS_GPU
))
5791 struct wined3d_resource_desc desc
;
5792 struct wined3d_box upload_box
;
5793 unsigned int src_level
;
5796 TRACE("Source texture is not GPU accessible, creating a staging texture.\n");
5798 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
5799 desc
.resource_type
= WINED3D_RTYPE_TEXTURE_2D
;
5800 desc
.format
= src_texture
->resource
.format
->id
;
5801 desc
.multisample_type
= src_texture
->resource
.multisample_type
;
5802 desc
.multisample_quality
= src_texture
->resource
.multisample_quality
;
5803 desc
.usage
= WINED3DUSAGE_PRIVATE
;
5804 desc
.bind_flags
= 0;
5805 desc
.access
= WINED3D_RESOURCE_ACCESS_GPU
;
5806 desc
.width
= wined3d_texture_get_level_width(src_texture
, src_level
);
5807 desc
.height
= wined3d_texture_get_level_height(src_texture
, src_level
);
5811 if (FAILED(hr
= wined3d_texture_create(device
, &desc
, 1, 1, 0,
5812 NULL
, NULL
, &wined3d_null_parent_ops
, &staging_texture
)))
5814 ERR("Failed to create staging texture, hr %#x.\n", hr
);
5815 return dst_location
;
5818 wined3d_box_set(&upload_box
, 0, 0, desc
.width
, desc
.height
, 0, desc
.depth
);
5819 wined3d_texture_upload_from_texture(staging_texture
, 0, 0, 0, 0,
5820 src_texture
, src_sub_resource_idx
, &upload_box
);
5822 src_texture
= staging_texture
;
5823 src_texture_gl
= wined3d_texture_gl(src_texture
);
5824 src_sub_resource_idx
= 0;
5828 /* Make sure the surface is up-to-date. This should probably use
5829 * surface_load_location() and worry about the destination surface
5830 * too, unless we're overwriting it completely. */
5831 wined3d_texture_load(src_texture
, context
, FALSE
);
5834 wined3d_context_gl_apply_ffp_blit_state(context_gl
, device
);
5836 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
5839 wined3d_texture_translate_drawable_coords(dst_texture
, context_gl
->window
, &r
);
5843 if (wined3d_settings
.offscreen_rendering_mode
== ORM_FBO
)
5847 if (dst_location
== WINED3D_LOCATION_DRAWABLE
)
5849 TRACE("Destination texture %p is onscreen.\n", dst_texture
);
5850 buffer
= wined3d_texture_get_gl_buffer(dst_texture
);
5854 TRACE("Destination texture %p is offscreen.\n", dst_texture
);
5855 buffer
= GL_COLOR_ATTACHMENT0
;
5857 wined3d_context_gl_apply_fbo_state_blit(context_gl
, GL_DRAW_FRAMEBUFFER
,
5858 dst_resource
, dst_sub_resource_idx
, NULL
, 0, dst_location
);
5859 wined3d_context_gl_set_draw_buffer(context_gl
, buffer
);
5860 wined3d_context_gl_check_fbo_status(context_gl
, GL_DRAW_FRAMEBUFFER
);
5861 context_invalidate_state(context
, STATE_FRAMEBUFFER
);
5864 gl_info
->gl_ops
.gl
.p_glEnable(src_texture_gl
->target
);
5865 checkGLcall("glEnable(target)");
5867 if (op
== WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
|| colour_key
)
5869 gl_info
->gl_ops
.gl
.p_glEnable(GL_ALPHA_TEST
);
5870 checkGLcall("glEnable(GL_ALPHA_TEST)");
5875 /* For P8 surfaces, the alpha component contains the palette index.
5876 * Which means that the colourkey is one of the palette entries. In
5877 * other cases pixels that should be masked away have alpha set to 0. */
5878 if (src_texture
->resource
.format
->id
== WINED3DFMT_P8_UINT
)
5879 gl_info
->gl_ops
.gl
.p_glAlphaFunc(GL_NOTEQUAL
,
5880 (float)src_texture
->async
.src_blt_color_key
.color_space_low_value
/ 255.0f
);
5882 gl_info
->gl_ops
.gl
.p_glAlphaFunc(GL_NOTEQUAL
, 0.0f
);
5883 checkGLcall("glAlphaFunc");
5886 wined3d_context_gl_draw_textured_quad(context_gl
, src_texture_gl
,
5887 src_sub_resource_idx
, src_rect
, dst_rect
, filter
);
5889 if (op
== WINED3D_BLIT_OP_COLOR_BLIT_ALPHATEST
|| colour_key
)
5891 gl_info
->gl_ops
.gl
.p_glDisable(GL_ALPHA_TEST
);
5892 checkGLcall("glDisable(GL_ALPHA_TEST)");
5895 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_2D
);
5896 checkGLcall("glDisable(GL_TEXTURE_2D)");
5897 if (gl_info
->supported
[ARB_TEXTURE_CUBE_MAP
])
5899 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB
);
5900 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
5902 if (gl_info
->supported
[ARB_TEXTURE_RECTANGLE
])
5904 gl_info
->gl_ops
.gl
.p_glDisable(GL_TEXTURE_RECTANGLE_ARB
);
5905 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
5908 if (dst_texture
->swapchain
&& dst_texture
->swapchain
->front_buffer
== dst_texture
)
5909 gl_info
->gl_ops
.gl
.p_glFlush();
5911 /* Restore the colour key parameters */
5912 wined3d_texture_set_color_key(src_texture
, WINED3D_CKEY_SRC_BLT
,
5913 (old_colour_key_flags
& WINED3D_CKEY_SRC_BLT
) ? &old_blt_key
: NULL
);
5915 if (staging_texture
)
5916 wined3d_texture_decref(staging_texture
);
5918 return dst_location
;
5921 static const struct wined3d_blitter_ops ffp_blitter_ops
=
5923 ffp_blitter_destroy
,
5928 void wined3d_ffp_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
5930 struct wined3d_blitter
*blitter
;
5932 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
5935 TRACE("Created blitter %p.\n", blitter
);
5937 blitter
->ops
= &ffp_blitter_ops
;
5938 blitter
->next
= *next
;
5942 static void fbo_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
5944 struct wined3d_blitter
*next
;
5946 if ((next
= blitter
->next
))
5947 next
->ops
->blitter_destroy(next
, context
);
5952 static void fbo_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
5953 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
5954 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
5956 struct wined3d_blitter
*next
;
5958 if ((next
= blitter
->next
))
5959 next
->ops
->blitter_clear(next
, device
, rt_count
, fb
, rect_count
,
5960 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
5963 static DWORD
fbo_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
5964 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
5965 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
5966 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
5967 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
5968 const struct wined3d_format
*resolve_format
)
5970 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
5971 struct wined3d_resource
*src_resource
, *dst_resource
;
5972 enum wined3d_blit_op blit_op
= op
;
5973 struct wined3d_device
*device
;
5974 struct wined3d_blitter
*next
;
5976 TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, "
5977 "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, "
5978 "colour_key %p, filter %s, resolve_format %p.\n",
5979 blitter
, op
, context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
5980 wine_dbgstr_rect(src_rect
), dst_texture
, dst_sub_resource_idx
, wined3d_debug_location(dst_location
),
5981 wine_dbgstr_rect(dst_rect
), colour_key
, debug_d3dtexturefiltertype(filter
), resolve_format
);
5983 src_resource
= &src_texture
->resource
;
5984 dst_resource
= &dst_texture
->resource
;
5986 device
= dst_resource
->device
;
5988 if (blit_op
== WINED3D_BLIT_OP_RAW_BLIT
&& dst_resource
->format
->id
== src_resource
->format
->id
)
5990 if (dst_resource
->format
->depth_size
|| dst_resource
->format
->stencil_size
)
5991 blit_op
= WINED3D_BLIT_OP_DEPTH_BLIT
;
5993 blit_op
= WINED3D_BLIT_OP_COLOR_BLIT
;
5996 if (!fbo_blitter_supported(blit_op
, context_gl
->gl_info
,
5997 src_resource
, src_location
, dst_resource
, dst_location
))
5999 if (!(next
= blitter
->next
))
6001 ERR("No blitter to handle blit op %#x.\n", op
);
6002 return dst_location
;
6005 TRACE("Forwarding to blitter %p.\n", next
);
6006 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6007 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
6011 if (blit_op
== WINED3D_BLIT_OP_COLOR_BLIT
)
6013 TRACE("Colour blit.\n");
6014 texture2d_blt_fbo(device
, context
, filter
, src_texture
, src_sub_resource_idx
, src_location
,
6015 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, resolve_format
);
6016 return dst_location
;
6019 if (blit_op
== WINED3D_BLIT_OP_DEPTH_BLIT
)
6021 TRACE("Depth/stencil blit.\n");
6022 texture2d_depth_blt_fbo(device
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6023 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
);
6024 return dst_location
;
6027 ERR("This blitter does not implement blit op %#x.\n", blit_op
);
6028 return dst_location
;
6031 static const struct wined3d_blitter_ops fbo_blitter_ops
=
6033 fbo_blitter_destroy
,
6038 void wined3d_fbo_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
6040 struct wined3d_blitter
*blitter
;
6042 if ((wined3d_settings
.offscreen_rendering_mode
!= ORM_FBO
) || !gl_info
->fbo_ops
.glBlitFramebuffer
)
6045 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6048 TRACE("Created blitter %p.\n", blitter
);
6050 blitter
->ops
= &fbo_blitter_ops
;
6051 blitter
->next
= *next
;
6055 static void raw_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
6057 struct wined3d_blitter
*next
;
6059 if ((next
= blitter
->next
))
6060 next
->ops
->blitter_destroy(next
, context
);
6065 static void raw_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
6066 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
6067 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
6069 struct wined3d_blitter
*next
;
6071 if (!(next
= blitter
->next
))
6073 ERR("No blitter to handle clear.\n");
6077 TRACE("Forwarding to blitter %p.\n", next
);
6078 next
->ops
->blitter_clear(next
, device
, rt_count
, fb
, rect_count
,
6079 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
6082 static DWORD
raw_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
6083 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
6084 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
6085 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
6086 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
6087 const struct wined3d_format
*resolve_format
)
6089 struct wined3d_texture_gl
*src_texture_gl
= wined3d_texture_gl(src_texture
);
6090 struct wined3d_texture_gl
*dst_texture_gl
= wined3d_texture_gl(dst_texture
);
6091 struct wined3d_context_gl
*context_gl
= wined3d_context_gl(context
);
6092 const struct wined3d_gl_info
*gl_info
= context_gl
->gl_info
;
6093 unsigned int src_level
, src_layer
, dst_level
, dst_layer
;
6094 struct wined3d_blitter
*next
;
6095 GLuint src_name
, dst_name
;
6096 bool src_ds
, dst_ds
;
6099 src_ds
= src_texture
->resource
.format
->depth_size
|| src_texture
->resource
.format
->stencil_size
;
6100 dst_ds
= dst_texture
->resource
.format
->depth_size
|| dst_texture
->resource
.format
->stencil_size
;
6102 /* If we would need to copy from a renderbuffer or drawable, we'd probably
6103 * be better off using the FBO blitter directly, since we'd need to use it
6104 * to copy the resource contents to the texture anyway.
6106 * We also can't copy between depth/stencil and colour resources, since
6107 * the formats are considered incompatible in OpenGL. */
6108 if (op
!= WINED3D_BLIT_OP_RAW_BLIT
|| (src_ds
!= dst_ds
)
6109 || (src_texture
->resource
.format
->id
== dst_texture
->resource
.format
->id
6110 && (!(src_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
))
6111 || !(dst_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
)))))
6113 if (!(next
= blitter
->next
))
6115 ERR("No blitter to handle blit op %#x.\n", op
);
6116 return dst_location
;
6119 TRACE("Forwarding to blitter %p.\n", next
);
6120 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6121 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
,
6125 TRACE("Blit using ARB_copy_image.\n");
6127 src_level
= src_sub_resource_idx
% src_texture
->level_count
;
6128 src_layer
= src_sub_resource_idx
/ src_texture
->level_count
;
6130 dst_level
= dst_sub_resource_idx
% dst_texture
->level_count
;
6131 dst_layer
= dst_sub_resource_idx
/ dst_texture
->level_count
;
6133 location
= src_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
6135 location
= src_texture
->flags
& WINED3D_TEXTURE_IS_SRGB
6136 ? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
6137 if (!wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, location
))
6138 ERR("Failed to load the source sub-resource into %s.\n", wined3d_debug_location(location
));
6139 src_name
= wined3d_texture_gl_get_texture_name(src_texture_gl
,
6140 context
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
6142 location
= dst_location
& (WINED3D_LOCATION_TEXTURE_RGB
| WINED3D_LOCATION_TEXTURE_SRGB
);
6144 location
= dst_texture
->flags
& WINED3D_TEXTURE_IS_SRGB
6145 ? WINED3D_LOCATION_TEXTURE_SRGB
: WINED3D_LOCATION_TEXTURE_RGB
;
6146 if (wined3d_texture_is_full_rect(dst_texture
, dst_level
, dst_rect
))
6148 if (!wined3d_texture_prepare_location(dst_texture
, dst_sub_resource_idx
, context
, location
))
6149 ERR("Failed to prepare the destination sub-resource into %s.\n", wined3d_debug_location(location
));
6153 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, location
))
6154 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(location
));
6156 dst_name
= wined3d_texture_gl_get_texture_name(dst_texture_gl
,
6157 context
, location
== WINED3D_LOCATION_TEXTURE_SRGB
);
6159 GL_EXTCALL(glCopyImageSubData(src_name
, src_texture_gl
->target
, src_level
,
6160 src_rect
->left
, src_rect
->top
, src_layer
, dst_name
, dst_texture_gl
->target
, dst_level
,
6161 dst_rect
->left
, dst_rect
->top
, dst_layer
, src_rect
->right
- src_rect
->left
,
6162 src_rect
->bottom
- src_rect
->top
, 1));
6163 checkGLcall("copy image data");
6165 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, location
);
6166 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~location
);
6167 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
))
6168 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location
));
6170 return dst_location
| location
;
6173 static const struct wined3d_blitter_ops raw_blitter_ops
=
6175 raw_blitter_destroy
,
6180 void wined3d_raw_blitter_create(struct wined3d_blitter
**next
, const struct wined3d_gl_info
*gl_info
)
6182 struct wined3d_blitter
*blitter
;
6184 if (!gl_info
->supported
[ARB_COPY_IMAGE
])
6187 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6190 TRACE("Created blitter %p.\n", blitter
);
6192 blitter
->ops
= &raw_blitter_ops
;
6193 blitter
->next
= *next
;
6197 static void vk_blitter_destroy(struct wined3d_blitter
*blitter
, struct wined3d_context
*context
)
6199 struct wined3d_blitter
*next
;
6201 TRACE("blitter %p, context %p.\n", blitter
, context
);
6203 if ((next
= blitter
->next
))
6204 next
->ops
->blitter_destroy(next
, context
);
6209 static void vk_blitter_clear_rendertargets(struct wined3d_context_vk
*context_vk
, unsigned int rt_count
,
6210 const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
, const RECT
*draw_rect
,
6211 uint32_t flags
, const struct wined3d_color
*colour
, float depth
, unsigned int stencil
)
6213 VkClearValue clear_values
[WINED3D_MAX_RENDER_TARGETS
+ 1];
6214 VkImageView views
[WINED3D_MAX_RENDER_TARGETS
+ 1];
6215 struct wined3d_rendertarget_view_vk
*rtv_vk
;
6216 struct wined3d_rendertarget_view
*view
;
6217 const struct wined3d_vk_info
*vk_info
;
6218 struct wined3d_device_vk
*device_vk
;
6219 VkCommandBuffer vk_command_buffer
;
6220 VkRenderPassBeginInfo begin_desc
;
6221 unsigned int i
, attachment_count
;
6222 VkFramebufferCreateInfo fb_desc
;
6223 VkFramebuffer vk_framebuffer
;
6224 VkRenderPass vk_render_pass
;
6225 bool depth_stencil
= false;
6226 unsigned int layer_count
;
6227 VkClearColorValue
*c
;
6231 TRACE("context_vk %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, "
6232 "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n",
6233 context_vk
, rt_count
, fb
, rect_count
, clear_rects
,
6234 wine_dbgstr_rect(draw_rect
), flags
, debug_color(colour
), depth
, stencil
);
6236 device_vk
= wined3d_device_vk(context_vk
->c
.device
);
6237 vk_info
= context_vk
->vk_info
;
6239 if (!(flags
& WINED3DCLEAR_TARGET
))
6242 for (i
= 0, attachment_count
= 0, layer_count
= 1; i
< rt_count
; ++i
)
6244 if (!(view
= fb
->render_targets
[i
]))
6247 if (!is_full_clear(view
, draw_rect
, clear_rects
))
6248 wined3d_rendertarget_view_load_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6250 wined3d_rendertarget_view_prepare_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6251 wined3d_rendertarget_view_validate_location(view
, view
->resource
->draw_binding
);
6252 wined3d_rendertarget_view_invalidate_location(view
, ~view
->resource
->draw_binding
);
6254 rtv_vk
= wined3d_rendertarget_view_vk(view
);
6255 views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
6256 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_RENDER_TARGET
);
6258 c
= &clear_values
[attachment_count
].color
;
6259 if (view
->format_flags
& WINED3DFMT_FLAG_INTEGER
)
6261 c
->int32
[0] = colour
->r
;
6262 c
->int32
[1] = colour
->g
;
6263 c
->int32
[2] = colour
->b
;
6264 c
->int32
[3] = colour
->a
;
6268 c
->float32
[0] = colour
->r
;
6269 c
->float32
[1] = colour
->g
;
6270 c
->float32
[2] = colour
->b
;
6271 c
->float32
[3] = colour
->a
;
6274 if (view
->layer_count
> layer_count
)
6275 layer_count
= view
->layer_count
;
6280 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
) && (view
= fb
->depth_stencil
))
6282 if (!is_full_clear(view
, draw_rect
, clear_rects
))
6283 wined3d_rendertarget_view_load_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6285 wined3d_rendertarget_view_prepare_location(view
, &context_vk
->c
, view
->resource
->draw_binding
);
6286 wined3d_rendertarget_view_validate_location(view
, view
->resource
->draw_binding
);
6287 wined3d_rendertarget_view_invalidate_location(view
, ~view
->resource
->draw_binding
);
6289 rtv_vk
= wined3d_rendertarget_view_vk(view
);
6290 views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
6291 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_DEPTH_STENCIL
);
6293 clear_values
[attachment_count
].depthStencil
.depth
= depth
;
6294 clear_values
[attachment_count
].depthStencil
.stencil
= stencil
;
6296 if (view
->layer_count
> layer_count
)
6297 layer_count
= view
->layer_count
;
6299 depth_stencil
= true;
6303 if (!attachment_count
)
6306 if (!(vk_render_pass
= wined3d_context_vk_get_render_pass(context_vk
, fb
,
6307 rt_count
, flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
), flags
)))
6309 ERR("Failed to get render pass.\n");
6313 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
6315 ERR("Failed to get command buffer.\n");
6319 fb_desc
.sType
= VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
;
6320 fb_desc
.pNext
= NULL
;
6322 fb_desc
.renderPass
= vk_render_pass
;
6323 fb_desc
.attachmentCount
= attachment_count
;
6324 fb_desc
.pAttachments
= views
;
6325 fb_desc
.width
= draw_rect
->right
- draw_rect
->left
;
6326 fb_desc
.height
= draw_rect
->bottom
- draw_rect
->top
;
6327 fb_desc
.layers
= layer_count
;
6328 if ((vr
= VK_CALL(vkCreateFramebuffer(device_vk
->vk_device
, &fb_desc
, NULL
, &vk_framebuffer
))) < 0)
6330 ERR("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr
));
6334 begin_desc
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
;
6335 begin_desc
.pNext
= NULL
;
6336 begin_desc
.renderPass
= vk_render_pass
;
6337 begin_desc
.framebuffer
= vk_framebuffer
;
6338 begin_desc
.clearValueCount
= attachment_count
;
6339 begin_desc
.pClearValues
= clear_values
;
6341 wined3d_context_vk_end_current_render_pass(context_vk
);
6343 for (i
= 0; i
< rect_count
; ++i
)
6345 r
.left
= max(clear_rects
[i
].left
, draw_rect
->left
);
6346 r
.top
= max(clear_rects
[i
].top
, draw_rect
->top
);
6347 r
.right
= min(clear_rects
[i
].right
, draw_rect
->right
);
6348 r
.bottom
= min(clear_rects
[i
].bottom
, draw_rect
->bottom
);
6350 if (r
.left
>= r
.right
|| r
.top
>= r
.bottom
)
6353 begin_desc
.renderArea
.offset
.x
= r
.left
;
6354 begin_desc
.renderArea
.offset
.y
= r
.top
;
6355 begin_desc
.renderArea
.extent
.width
= r
.right
- r
.left
;
6356 begin_desc
.renderArea
.extent
.height
= r
.bottom
- r
.top
;
6357 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer
, &begin_desc
, VK_SUBPASS_CONTENTS_INLINE
));
6358 VK_CALL(vkCmdEndRenderPass(vk_command_buffer
));
6361 wined3d_context_vk_destroy_vk_framebuffer(context_vk
, vk_framebuffer
, context_vk
->current_command_buffer
.id
);
6363 for (i
= 0; i
< rt_count
; ++i
)
6365 if (!(view
= fb
->render_targets
[i
]))
6368 wined3d_context_vk_reference_rendertarget_view(context_vk
, wined3d_rendertarget_view_vk(view
));
6373 view
= fb
->depth_stencil
;
6374 wined3d_context_vk_reference_rendertarget_view(context_vk
, wined3d_rendertarget_view_vk(view
));
6378 static void vk_blitter_clear(struct wined3d_blitter
*blitter
, struct wined3d_device
*device
,
6379 unsigned int rt_count
, const struct wined3d_fb_state
*fb
, unsigned int rect_count
, const RECT
*clear_rects
,
6380 const RECT
*draw_rect
, DWORD flags
, const struct wined3d_color
*colour
, float depth
, DWORD stencil
)
6382 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(device
);
6383 struct wined3d_rendertarget_view
*view
, *previous
= NULL
;
6384 struct wined3d_context_vk
*context_vk
;
6385 bool have_identical_size
= true;
6386 struct wined3d_fb_state tmp_fb
;
6387 unsigned int next_rt_count
= 0;
6388 struct wined3d_blitter
*next
;
6389 uint32_t next_flags
= 0;
6392 TRACE("blitter %p, device %p, rt_count %u, fb %p, rect_count %u, clear_rects %p, "
6393 "draw_rect %s, flags %#x, colour %s, depth %.8e, stencil %#x.\n",
6394 blitter
, device
, rt_count
, fb
, rect_count
, clear_rects
,
6395 wine_dbgstr_rect(draw_rect
), flags
, debug_color(colour
), depth
, stencil
);
6400 clear_rects
= draw_rect
;
6403 if (flags
& WINED3DCLEAR_TARGET
)
6405 for (i
= 0; i
< rt_count
; ++i
)
6407 if (!(view
= fb
->render_targets
[i
]))
6410 if (blitter_use_cpu_clear(view
))
6412 next_flags
|= WINED3DCLEAR_TARGET
;
6413 flags
&= ~WINED3DCLEAR_TARGET
;
6414 next_rt_count
= rt_count
;
6421 if ((flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
)) && (view
= fb
->depth_stencil
)
6422 && (!view
->format
->depth_size
|| (flags
& WINED3DCLEAR_ZBUFFER
))
6423 && (!view
->format
->stencil_size
|| (flags
& WINED3DCLEAR_STENCIL
))
6424 && blitter_use_cpu_clear(view
))
6426 next_flags
|= flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
6427 flags
&= ~(WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
);
6432 context_vk
= wined3d_context_vk(context_acquire(&device_vk
->d
, NULL
, 0));
6434 for (i
= 0; i
< rt_count
; ++i
)
6436 if (!(view
= fb
->render_targets
[i
]))
6439 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
6440 have_identical_size
= false;
6443 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
6445 view
= fb
->depth_stencil
;
6447 if (previous
&& (previous
->width
!= view
->width
|| previous
->height
!= view
->height
))
6448 have_identical_size
= false;
6451 if (have_identical_size
)
6453 vk_blitter_clear_rendertargets(context_vk
, rt_count
, fb
, rect_count
,
6454 clear_rects
, draw_rect
, flags
, colour
, depth
, stencil
);
6458 for (i
= 0; i
< rt_count
; ++i
)
6460 if (!(view
= fb
->render_targets
[i
]))
6463 tmp_fb
.render_targets
[0] = view
;
6464 tmp_fb
.depth_stencil
= NULL
;
6465 vk_blitter_clear_rendertargets(context_vk
, 1, &tmp_fb
, rect_count
,
6466 clear_rects
, draw_rect
, WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
6468 if (flags
& (WINED3DCLEAR_ZBUFFER
| WINED3DCLEAR_STENCIL
))
6470 tmp_fb
.render_targets
[0] = NULL
;
6471 tmp_fb
.depth_stencil
= fb
->depth_stencil
;
6472 vk_blitter_clear_rendertargets(context_vk
, 0, &tmp_fb
, rect_count
,
6473 clear_rects
, draw_rect
, flags
& ~WINED3DCLEAR_TARGET
, colour
, depth
, stencil
);
6477 context_release(&context_vk
->c
);
6483 if (!(next
= blitter
->next
))
6485 ERR("No blitter to handle clear.\n");
6489 TRACE("Forwarding to blitter %p.\n", next
);
6490 next
->ops
->blitter_clear(next
, device
, next_rt_count
, fb
, rect_count
,
6491 clear_rects
, draw_rect
, next_flags
, colour
, depth
, stencil
);
6494 static bool vk_blitter_blit_supported(enum wined3d_blit_op op
, const struct wined3d_context
*context
,
6495 const struct wined3d_resource
*src_resource
, const RECT
*src_rect
,
6496 const struct wined3d_resource
*dst_resource
, const RECT
*dst_rect
, const struct wined3d_format
*resolve_format
)
6498 const struct wined3d_format
*src_format
= src_resource
->format
;
6499 const struct wined3d_format
*dst_format
= dst_resource
->format
;
6501 if (!(dst_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
6503 TRACE("Destination resource does not have GPU access.\n");
6507 if (!(src_resource
->access
& WINED3D_RESOURCE_ACCESS_GPU
))
6509 TRACE("Source resource does not have GPU access.\n");
6513 if (dst_format
->id
!= src_format
->id
)
6515 if (!is_identity_fixup(dst_format
->color_fixup
))
6517 TRACE("Destination fixups are not supported.\n");
6521 if (!is_identity_fixup(src_format
->color_fixup
))
6523 TRACE("Source fixups are not supported.\n");
6527 if (op
!= WINED3D_BLIT_OP_RAW_BLIT
6528 && wined3d_format_vk(src_format
)->vk_format
!= wined3d_format_vk(dst_format
)->vk_format
6529 && ((!wined3d_format_is_typeless(src_format
) && !wined3d_format_is_typeless(dst_format
))
6530 || !resolve_format
))
6532 TRACE("Format conversion not supported.\n");
6537 if (wined3d_resource_get_sample_count(dst_resource
) > 1)
6539 TRACE("Multi-sample destination resource not supported.\n");
6543 if (op
== WINED3D_BLIT_OP_RAW_BLIT
)
6546 if (op
!= WINED3D_BLIT_OP_COLOR_BLIT
)
6548 TRACE("Unsupported blit operation %#x.\n", op
);
6552 if ((src_rect
->right
- src_rect
->left
!= dst_rect
->right
- dst_rect
->left
)
6553 || (src_rect
->bottom
- src_rect
->top
!= dst_rect
->bottom
- dst_rect
->top
))
6555 TRACE("Scaling not supported.\n");
6562 static DWORD
vk_blitter_blit(struct wined3d_blitter
*blitter
, enum wined3d_blit_op op
,
6563 struct wined3d_context
*context
, struct wined3d_texture
*src_texture
, unsigned int src_sub_resource_idx
,
6564 DWORD src_location
, const RECT
*src_rect
, struct wined3d_texture
*dst_texture
,
6565 unsigned int dst_sub_resource_idx
, DWORD dst_location
, const RECT
*dst_rect
,
6566 const struct wined3d_color_key
*colour_key
, enum wined3d_texture_filter_type filter
,
6567 const struct wined3d_format
*resolve_format
)
6569 struct wined3d_texture_vk
*src_texture_vk
= wined3d_texture_vk(src_texture
);
6570 struct wined3d_texture_vk
*dst_texture_vk
= wined3d_texture_vk(dst_texture
);
6571 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
6572 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
6573 VkImageSubresourceRange vk_src_range
, vk_dst_range
;
6574 VkCommandBuffer vk_command_buffer
;
6575 struct wined3d_blitter
*next
;
6576 unsigned src_sample_count
;
6577 bool resolve
= false;
6579 TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, "
6580 "src_rect %s, dst_texture %p, dst_sub_resource_idx %u, dst_location %s, dst_rect %s, "
6581 "colour_key %p, filter %s, resolve format %p.\n",
6582 blitter
, op
, context
, src_texture
, src_sub_resource_idx
, wined3d_debug_location(src_location
),
6583 wine_dbgstr_rect(src_rect
), dst_texture
, dst_sub_resource_idx
, wined3d_debug_location(dst_location
),
6584 wine_dbgstr_rect(dst_rect
), colour_key
, debug_d3dtexturefiltertype(filter
), resolve_format
);
6586 if (!vk_blitter_blit_supported(op
, context
, &src_texture
->resource
, src_rect
, &dst_texture
->resource
, dst_rect
,
6590 src_sample_count
= wined3d_resource_get_sample_count(&src_texture_vk
->t
.resource
);
6591 if (src_sample_count
> 1)
6594 vk_src_range
.aspectMask
= vk_aspect_mask_from_format(src_texture_vk
->t
.resource
.format
);
6595 vk_src_range
.baseMipLevel
= src_sub_resource_idx
% src_texture
->level_count
;
6596 vk_src_range
.levelCount
= 1;
6597 vk_src_range
.baseArrayLayer
= src_sub_resource_idx
/ src_texture
->level_count
;
6598 vk_src_range
.layerCount
= 1;
6600 vk_dst_range
.aspectMask
= vk_aspect_mask_from_format(dst_texture_vk
->t
.resource
.format
);
6601 vk_dst_range
.baseMipLevel
= dst_sub_resource_idx
% dst_texture
->level_count
;
6602 vk_dst_range
.levelCount
= 1;
6603 vk_dst_range
.baseArrayLayer
= dst_sub_resource_idx
/ dst_texture
->level_count
;
6604 vk_dst_range
.layerCount
= 1;
6606 if (!wined3d_texture_load_location(src_texture
, src_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6607 ERR("Failed to load the source sub-resource.\n");
6609 if (wined3d_texture_is_full_rect(dst_texture
, vk_dst_range
.baseMipLevel
, dst_rect
))
6611 if (!wined3d_texture_prepare_location(dst_texture
,
6612 dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6614 ERR("Failed to prepare the destination sub-resource.\n");
6620 if (!wined3d_texture_load_location(dst_texture
,
6621 dst_sub_resource_idx
, context
, WINED3D_LOCATION_TEXTURE_RGB
))
6623 ERR("Failed to load the destination sub-resource.\n");
6628 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
6630 ERR("Failed to get command buffer.\n");
6634 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6635 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6636 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6637 VK_ACCESS_TRANSFER_READ_BIT
,
6638 src_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6639 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6640 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6641 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6642 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6643 VK_ACCESS_TRANSFER_WRITE_BIT
,
6644 dst_texture_vk
->layout
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
6645 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6649 const struct wined3d_format_vk
*src_format_vk
= wined3d_format_vk(src_texture
->resource
.format
);
6650 const struct wined3d_format_vk
*dst_format_vk
= wined3d_format_vk(dst_texture
->resource
.format
);
6651 const unsigned int usage
= VK_IMAGE_USAGE_TRANSFER_SRC_BIT
6652 | VK_IMAGE_USAGE_TRANSFER_DST_BIT
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
;
6653 VkImage src_vk_image
, dst_vk_image
;
6654 VkImageSubresourceRange vk_range
;
6655 VkImageResolve resolve_region
;
6656 VkImageType vk_image_type
;
6657 VkImageCopy copy_region
;
6662 vk_format
= wined3d_format_vk(resolve_format
)->vk_format
;
6664 else if (!wined3d_format_is_typeless(src_texture
->resource
.format
))
6666 vk_format
= src_format_vk
->vk_format
;
6670 vk_format
= dst_format_vk
->vk_format
;
6673 switch (src_texture
->resource
.type
)
6675 case WINED3D_RTYPE_TEXTURE_1D
:
6676 vk_image_type
= VK_IMAGE_TYPE_1D
;
6678 case WINED3D_RTYPE_TEXTURE_2D
:
6679 vk_image_type
= VK_IMAGE_TYPE_2D
;
6681 case WINED3D_RTYPE_TEXTURE_3D
:
6682 vk_image_type
= VK_IMAGE_TYPE_3D
;
6685 ERR("Unexpected resource type: %s\n", debug_d3dresourcetype(src_texture
->resource
.type
));
6689 vk_range
.baseMipLevel
= 0;
6690 vk_range
.levelCount
= 1;
6691 vk_range
.baseArrayLayer
= 0;
6692 vk_range
.layerCount
= 1;
6694 resolve_region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6695 resolve_region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6696 resolve_region
.extent
.width
= src_rect
->right
- src_rect
->left
;
6697 resolve_region
.extent
.height
= src_rect
->bottom
- src_rect
->top
;
6698 resolve_region
.extent
.depth
= 1;
6700 /* In case of typeless resolve the texture type may not match the resolve type.
6701 * To handle that, allocate intermediate texture(s) to resolve from/to.
6702 * A possible performance improvement would be to resolve using a shader instead. */
6703 if (src_format_vk
->vk_format
!= vk_format
)
6705 struct wined3d_image_vk src_image
;
6707 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, usage
, vk_format
,
6708 resolve_region
.extent
.width
, resolve_region
.extent
.height
, 1,
6709 src_sample_count
, 1, 1, 0, &src_image
))
6712 wined3d_context_vk_reference_image(context_vk
, &src_image
);
6713 src_vk_image
= src_image
.vk_image
;
6714 wined3d_context_vk_destroy_image(context_vk
, &src_image
);
6716 vk_range
.aspectMask
= vk_src_range
.aspectMask
;
6718 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6719 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6720 0, VK_ACCESS_TRANSFER_WRITE_BIT
, VK_IMAGE_LAYOUT_UNDEFINED
,
6721 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, src_vk_image
, &vk_range
);
6723 copy_region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6724 copy_region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6725 copy_region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6726 copy_region
.srcSubresource
.layerCount
= 1;
6727 copy_region
.srcOffset
.x
= src_rect
->left
;
6728 copy_region
.srcOffset
.y
= src_rect
->top
;
6729 copy_region
.srcOffset
.z
= 0;
6730 copy_region
.dstSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6731 copy_region
.dstSubresource
.mipLevel
= 0;
6732 copy_region
.dstSubresource
.baseArrayLayer
= 0;
6733 copy_region
.dstSubresource
.layerCount
= 1;
6734 copy_region
.dstOffset
.x
= 0;
6735 copy_region
.dstOffset
.y
= 0;
6736 copy_region
.dstOffset
.z
= 0;
6737 copy_region
.extent
.width
= resolve_region
.extent
.width
;
6738 copy_region
.extent
.height
= resolve_region
.extent
.height
;
6739 copy_region
.extent
.depth
= 1;
6741 VK_CALL(vkCmdCopyImage(vk_command_buffer
, src_texture_vk
->image
.vk_image
,
6742 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
,
6745 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6746 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6747 VK_ACCESS_TRANSFER_WRITE_BIT
, VK_ACCESS_TRANSFER_READ_BIT
,
6748 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6749 src_vk_image
, &vk_range
);
6751 resolve_region
.srcSubresource
.mipLevel
= 0;
6752 resolve_region
.srcSubresource
.baseArrayLayer
= 0;
6753 resolve_region
.srcSubresource
.layerCount
= 1;
6754 resolve_region
.srcOffset
.x
= 0;
6755 resolve_region
.srcOffset
.y
= 0;
6756 resolve_region
.srcOffset
.z
= 0;
6760 src_vk_image
= src_texture_vk
->image
.vk_image
;
6762 resolve_region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6763 resolve_region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6764 resolve_region
.srcSubresource
.layerCount
= 1;
6765 resolve_region
.srcOffset
.x
= src_rect
->left
;
6766 resolve_region
.srcOffset
.y
= src_rect
->top
;
6767 resolve_region
.srcOffset
.z
= 0;
6770 if (dst_format_vk
->vk_format
!= vk_format
)
6772 struct wined3d_image_vk dst_image
;
6774 if (!wined3d_context_vk_create_image(context_vk
, vk_image_type
, usage
, vk_format
,
6775 resolve_region
.extent
.width
, resolve_region
.extent
.height
, 1,
6776 VK_SAMPLE_COUNT_1_BIT
, 1, 1, 0, &dst_image
))
6779 wined3d_context_vk_reference_image(context_vk
, &dst_image
);
6780 dst_vk_image
= dst_image
.vk_image
;
6781 wined3d_context_vk_destroy_image(context_vk
, &dst_image
);
6783 vk_range
.aspectMask
= vk_dst_range
.aspectMask
;
6784 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6785 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
, 0, VK_ACCESS_TRANSFER_WRITE_BIT
,
6786 VK_IMAGE_LAYOUT_UNDEFINED
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_vk_image
, &vk_range
);
6788 resolve_region
.dstSubresource
.mipLevel
= 0;
6789 resolve_region
.dstSubresource
.baseArrayLayer
= 0;
6790 resolve_region
.dstSubresource
.layerCount
= 1;
6791 resolve_region
.dstOffset
.x
= 0;
6792 resolve_region
.dstOffset
.y
= 0;
6793 resolve_region
.dstOffset
.z
= 0;
6797 dst_vk_image
= dst_texture_vk
->image
.vk_image
;
6799 resolve_region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6800 resolve_region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6801 resolve_region
.dstSubresource
.layerCount
= 1;
6802 resolve_region
.dstOffset
.x
= dst_rect
->left
;
6803 resolve_region
.dstOffset
.y
= dst_rect
->top
;
6804 resolve_region
.dstOffset
.z
= 0;
6807 VK_CALL(vkCmdResolveImage(vk_command_buffer
, src_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6808 dst_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, &resolve_region
));
6810 if (dst_vk_image
!= dst_texture_vk
->image
.vk_image
)
6812 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6813 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
6814 VK_ACCESS_TRANSFER_WRITE_BIT
, VK_ACCESS_TRANSFER_READ_BIT
,
6815 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6816 dst_vk_image
, &vk_range
);
6818 copy_region
.srcSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6819 copy_region
.srcSubresource
.mipLevel
= 0;
6820 copy_region
.srcSubresource
.baseArrayLayer
= 0;
6821 copy_region
.srcSubresource
.layerCount
= 1;
6822 copy_region
.srcOffset
.x
= 0;
6823 copy_region
.srcOffset
.y
= 0;
6824 copy_region
.srcOffset
.z
= 0;
6825 copy_region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6826 copy_region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6827 copy_region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6828 copy_region
.dstSubresource
.layerCount
= 1;
6829 copy_region
.dstOffset
.x
= dst_rect
->left
;
6830 copy_region
.dstOffset
.y
= dst_rect
->top
;
6831 copy_region
.dstOffset
.z
= 0;
6832 copy_region
.extent
.width
= resolve_region
.extent
.width
;
6833 copy_region
.extent
.height
= resolve_region
.extent
.height
;
6834 copy_region
.extent
.depth
= 1;
6836 VK_CALL(vkCmdCopyImage(vk_command_buffer
, dst_vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6837 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ©_region
));
6844 region
.srcSubresource
.aspectMask
= vk_src_range
.aspectMask
;
6845 region
.srcSubresource
.mipLevel
= vk_src_range
.baseMipLevel
;
6846 region
.srcSubresource
.baseArrayLayer
= vk_src_range
.baseArrayLayer
;
6847 region
.srcSubresource
.layerCount
= vk_src_range
.layerCount
;
6848 region
.srcOffset
.x
= src_rect
->left
;
6849 region
.srcOffset
.y
= src_rect
->top
;
6850 region
.srcOffset
.z
= 0;
6851 region
.dstSubresource
.aspectMask
= vk_dst_range
.aspectMask
;
6852 region
.dstSubresource
.mipLevel
= vk_dst_range
.baseMipLevel
;
6853 region
.dstSubresource
.baseArrayLayer
= vk_dst_range
.baseArrayLayer
;
6854 region
.dstSubresource
.layerCount
= vk_dst_range
.layerCount
;
6855 region
.dstOffset
.x
= dst_rect
->left
;
6856 region
.dstOffset
.y
= dst_rect
->top
;
6857 region
.dstOffset
.z
= 0;
6858 region
.extent
.width
= src_rect
->right
- src_rect
->left
;
6859 region
.extent
.height
= src_rect
->bottom
- src_rect
->top
;
6860 region
.extent
.depth
= 1;
6862 VK_CALL(vkCmdCopyImage(vk_command_buffer
, src_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
,
6863 dst_texture_vk
->image
.vk_image
, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, 1, ®ion
));
6866 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6867 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6868 VK_ACCESS_TRANSFER_WRITE_BIT
,
6869 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6870 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
6871 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6872 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6873 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6874 VK_ACCESS_TRANSFER_READ_BIT
,
6875 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6876 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
6877 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6879 wined3d_texture_validate_location(dst_texture
, dst_sub_resource_idx
, WINED3D_LOCATION_TEXTURE_RGB
);
6880 wined3d_texture_invalidate_location(dst_texture
, dst_sub_resource_idx
, ~WINED3D_LOCATION_TEXTURE_RGB
);
6881 if (!wined3d_texture_load_location(dst_texture
, dst_sub_resource_idx
, context
, dst_location
))
6882 ERR("Failed to load the destination sub-resource into %s.\n", wined3d_debug_location(dst_location
));
6884 wined3d_context_vk_reference_texture(context_vk
, src_texture_vk
);
6885 wined3d_context_vk_reference_texture(context_vk
, dst_texture_vk
);
6887 return dst_location
| WINED3D_LOCATION_TEXTURE_RGB
;
6890 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6891 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6892 VK_ACCESS_TRANSFER_WRITE_BIT
,
6893 vk_access_mask_from_bind_flags(dst_texture_vk
->t
.resource
.bind_flags
),
6894 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
, dst_texture_vk
->layout
,
6895 dst_texture_vk
->image
.vk_image
, &vk_dst_range
);
6896 wined3d_context_vk_image_barrier(context_vk
, vk_command_buffer
,
6897 VK_PIPELINE_STAGE_TRANSFER_BIT
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
6898 VK_ACCESS_TRANSFER_READ_BIT
,
6899 vk_access_mask_from_bind_flags(src_texture_vk
->t
.resource
.bind_flags
),
6900 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
, src_texture_vk
->layout
,
6901 src_texture_vk
->image
.vk_image
, &vk_src_range
);
6904 if (!(next
= blitter
->next
))
6906 ERR("No blitter to handle blit op %#x.\n", op
);
6907 return dst_location
;
6910 TRACE("Forwarding to blitter %p.\n", next
);
6911 return next
->ops
->blitter_blit(next
, op
, context
, src_texture
, src_sub_resource_idx
, src_location
,
6912 src_rect
, dst_texture
, dst_sub_resource_idx
, dst_location
, dst_rect
, colour_key
, filter
, resolve_format
);
6915 static const struct wined3d_blitter_ops vk_blitter_ops
=
6917 .blitter_destroy
= vk_blitter_destroy
,
6918 .blitter_clear
= vk_blitter_clear
,
6919 .blitter_blit
= vk_blitter_blit
,
6922 void wined3d_vk_blitter_create(struct wined3d_blitter
**next
)
6924 struct wined3d_blitter
*blitter
;
6926 if (!(blitter
= heap_alloc(sizeof(*blitter
))))
6929 TRACE("Created blitter %p.\n", blitter
);
6931 blitter
->ops
= &vk_blitter_ops
;
6932 blitter
->next
= *next
;