* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#include "config.h"
+#include "wine/port.h"
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
-static DWORD resource_access_from_pool(enum wined3d_pool pool)
-{
- switch (pool)
- {
- case WINED3D_POOL_DEFAULT:
- return WINED3D_RESOURCE_ACCESS_GPU;
-
- case WINED3D_POOL_MANAGED:
- return WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_CPU;
-
- case WINED3D_POOL_SCRATCH:
- case WINED3D_POOL_SYSTEM_MEM:
- return WINED3D_RESOURCE_ACCESS_CPU;
-
- default:
- FIXME("Unhandled pool %#x.\n", pool);
- return 0;
- }
-}
-
static void resource_check_usage(DWORD usage)
{
- static const DWORD handled = WINED3DUSAGE_RENDERTARGET
+ static DWORD handled = WINED3DUSAGE_RENDERTARGET
| WINED3DUSAGE_DEPTHSTENCIL
| WINED3DUSAGE_WRITEONLY
| WINED3DUSAGE_DYNAMIC
- | WINED3DUSAGE_AUTOGENMIPMAP
| WINED3DUSAGE_STATICDECL
| WINED3DUSAGE_OVERLAY
+ | WINED3DUSAGE_SCRATCH
| WINED3DUSAGE_PRIVATE
| WINED3DUSAGE_LEGACY_CUBEMAP
| WINED3DUSAGE_TEXTURE;
* driver. */
if (usage & ~handled)
+ {
FIXME("Unhandled usage flags %#x.\n", usage & ~handled);
+ handled |= usage;
+ }
if ((usage & (WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_WRITEONLY)) == WINED3DUSAGE_DYNAMIC)
WARN_(d3d_perf)("WINED3DUSAGE_DYNAMIC used without WINED3DUSAGE_WRITEONLY.\n");
}
HRESULT resource_init(struct wined3d_resource *resource, struct wined3d_device *device,
enum wined3d_resource_type type, const struct wined3d_format *format,
- enum wined3d_multisample_type multisample_type, UINT multisample_quality,
- DWORD usage, enum wined3d_pool pool, UINT width, UINT height, UINT depth, UINT size,
- void *parent, const struct wined3d_parent_ops *parent_ops,
+ enum wined3d_multisample_type multisample_type, unsigned int multisample_quality,
+ unsigned int usage, unsigned int access, unsigned int width, unsigned int height, unsigned int depth,
+ unsigned int size, void *parent, const struct wined3d_parent_ops *parent_ops,
const struct wined3d_resource_ops *resource_ops)
{
enum wined3d_gl_resource_type base_type = WINED3D_GL_RES_TYPE_COUNT;
resource_types[] =
{
{WINED3D_RTYPE_BUFFER, 0, WINED3D_GL_RES_TYPE_BUFFER},
+ {WINED3D_RTYPE_TEXTURE_1D, 0, WINED3D_GL_RES_TYPE_TEX_1D},
{WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_TEX_2D},
{WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_TEX_RECT},
{WINED3D_RTYPE_TEXTURE_2D, 0, WINED3D_GL_RES_TYPE_RB},
resource_check_usage(usage);
+ if (usage & WINED3DUSAGE_SCRATCH && access & WINED3D_RESOURCE_ACCESS_GPU)
+ {
+ ERR("Trying to create a scratch resource with access flags %s.\n",
+ wined3d_debug_resource_access(access));
+ return WINED3DERR_INVALIDCALL;
+ }
+
for (i = 0; i < ARRAY_SIZE(resource_types); ++i)
{
if (resource_types[i].type != type
* Use 2D textures, the texture code will pad to a power of 2 size. */
gl_type = WINED3D_GL_RES_TYPE_TEX_2D;
}
- else if (pool == WINED3D_POOL_SCRATCH)
+ else if (usage & WINED3DUSAGE_SCRATCH)
{
/* Needed for proper format information. */
gl_type = base_type;
resource->multisample_type = multisample_type;
resource->multisample_quality = multisample_quality;
resource->usage = usage;
- resource->pool = pool;
- resource->access_flags = resource_access_from_pool(pool);
- if (usage & WINED3DUSAGE_DYNAMIC)
- resource->access_flags |= WINED3D_RESOURCE_ACCESS_CPU;
+ resource->access = access;
resource->width = width;
resource->height = height;
resource->depth = depth;
if (!(usage & WINED3DUSAGE_PRIVATE))
{
/* Check that we have enough video ram left */
- if (pool == WINED3D_POOL_DEFAULT && device->wined3d->flags & WINED3D_VIDMEM_ACCOUNTING)
+ if (!(access & WINED3D_RESOURCE_ACCESS_CPU) && device->wined3d->flags & WINED3D_VIDMEM_ACCOUNTING)
{
if (size > wined3d_device_get_available_texture_mem(device))
{
if (!(resource->usage & WINED3DUSAGE_PRIVATE))
{
- if (resource->pool == WINED3D_POOL_DEFAULT && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
+ if (!(resource->access & WINED3D_RESOURCE_ACCESS_CPU) && d3d->flags & WINED3D_VIDMEM_ACCOUNTING)
{
TRACE("Decrementing device memory pool by %u.\n", resource->size);
adapter_adjust_memory(resource->device->adapter, (INT64)0 - resource->size);
{
DWORD prev;
- if (resource->pool != WINED3D_POOL_MANAGED)
+ if (!wined3d_resource_access_is_managed(resource->access))
{
WARN("Called on non-managed resource %p, ignoring.\n", resource);
return 0;
desc->multisample_type = resource->multisample_type;
desc->multisample_quality = resource->multisample_quality;
desc->usage = resource->usage;
- desc->pool = resource->pool;
+ desc->access = resource->access;
desc->width = resource->width;
desc->height = resource->height;
desc->depth = resource->depth;
{
/* Not all flags make sense together, but Windows never returns an error.
* Catch the cases that could cause issues. */
- if (flags & WINED3D_MAP_READONLY)
+ if (flags & WINED3D_MAP_READ)
{
if (flags & WINED3D_MAP_DISCARD)
{
- WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
- return 0;
+ WARN("WINED3D_MAP_READ combined with WINED3D_MAP_DISCARD, ignoring flags.\n");
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
if (flags & WINED3D_MAP_NOOVERWRITE)
{
- WARN("WINED3D_MAP_READONLY combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
- return 0;
+ WARN("WINED3D_MAP_READ combined with WINED3D_MAP_NOOVERWRITE, ignoring flags.\n");
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
}
else if (flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
if (!(resource->usage & WINED3DUSAGE_DYNAMIC))
{
WARN("DISCARD or NOOVERWRITE map on non-dynamic buffer, ignoring.\n");
- return 0;
+ return flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE);
}
if ((flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
== (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
TRACE("resource %p, sub_resource_idx %u, map_desc %p, box %s, flags %#x.\n",
resource, sub_resource_idx, map_desc, debug_box(box), flags);
+ if (!(flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE)))
+ {
+ WARN("No read/write flags specified.\n");
+ return E_INVALIDARG;
+ }
+
+ if ((flags & WINED3D_MAP_READ) && !(resource->access & WINED3D_RESOURCE_ACCESS_MAP_R))
+ {
+ WARN("Resource does not have MAP_R access.\n");
+ return E_INVALIDARG;
+ }
+
+ if ((flags & WINED3D_MAP_WRITE) && !(resource->access & WINED3D_RESOURCE_ACCESS_MAP_W))
+ {
+ WARN("Resource does not have MAP_W access.\n");
+ return E_INVALIDARG;
+ }
+
flags = wined3d_resource_sanitise_map_flags(resource, flags);
wined3d_resource_wait_idle(resource);
return wined3d_cs_map(resource->device->cs, resource, sub_resource_idx, map_desc, box, flags);
}
+HRESULT CDECL wined3d_resource_map_info(struct wined3d_resource *resource, unsigned int sub_resource_idx,
+ struct wined3d_map_info *info, DWORD flags)
+{
+ TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx);
+
+ return resource->resource_ops->resource_map_info(resource, sub_resource_idx, info, flags);
+}
+
HRESULT CDECL wined3d_resource_unmap(struct wined3d_resource *resource, unsigned int sub_resource_idx)
{
TRACE("resource %p, sub_resource_idx %u.\n", resource, sub_resource_idx);
return wined3d_cs_unmap(resource->device->cs, resource, sub_resource_idx);
}
+UINT CDECL wined3d_resource_update_info(struct wined3d_resource *resource, unsigned int sub_resource_idx,
+ const struct wined3d_box *box, unsigned int row_pitch, unsigned int depth_pitch)
+{
+ unsigned int width, height, depth;
+ struct wined3d_box b;
+ UINT data_size;
+
+ TRACE("resource %p, sub_resource_idx %u, box %s, row_pitch %u, depth_pitch %u.\n",
+ resource, sub_resource_idx, debug_box(box), row_pitch, depth_pitch);
+
+ if (resource->type == WINED3D_RTYPE_BUFFER)
+ {
+ if (sub_resource_idx > 0)
+ {
+ WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+ return 0;
+ }
+
+ width = resource->size;
+ height = 1;
+ depth = 1;
+ }
+ else if (resource->type == WINED3D_RTYPE_TEXTURE_1D ||
+ resource->type == WINED3D_RTYPE_TEXTURE_2D || resource->type == WINED3D_RTYPE_TEXTURE_3D)
+ {
+ struct wined3d_texture *texture = texture_from_resource(resource);
+ unsigned int level;
+
+ if (sub_resource_idx >= texture->level_count * texture->layer_count)
+ {
+ WARN("Invalid sub_resource_idx %u.\n", sub_resource_idx);
+ return 0;
+ }
+
+ level = sub_resource_idx % texture->level_count;
+ width = wined3d_texture_get_level_width(texture, level);
+ height = wined3d_texture_get_level_height(texture, level);
+ depth = wined3d_texture_get_level_depth(texture, level);
+ }
+ else
+ {
+ FIXME("Not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
+ return 0;
+ }
+
+ if (!box)
+ {
+ wined3d_box_set(&b, 0, 0, width, height, 0, depth);
+ box = &b;
+ }
+ else if (box->left >= box->right || box->right > width
+ || box->top >= box->bottom || box->bottom > height
+ || box->front >= box->back || box->back > depth)
+ {
+ WARN("Invalid box %s specified.\n", debug_box(box));
+ return 0;
+ }
+
+ if (resource->format_flags & WINED3DFMT_FLAG_BLOCKS)
+ {
+ if (resource->type != WINED3D_RTYPE_TEXTURE_2D)
+ {
+ FIXME("Calculation of block formats not implemented for %s resources.\n", debug_d3dresourcetype(resource->type));
+ return 0;
+ }
+
+ height = (box->bottom - box->top + resource->format->block_height - 1) / resource->format->block_height;
+ width = (box->right - box->left + resource->format->block_width - 1) / resource->format->block_width;
+ return (height - 1) * row_pitch + width * resource->format->block_byte_count;
+ }
+
+ data_size = 0;
+ switch (resource->type)
+ {
+ case WINED3D_RTYPE_TEXTURE_3D:
+ data_size += (box->back - box->front - 1) * depth_pitch;
+ /* fall-through */
+ case WINED3D_RTYPE_TEXTURE_2D:
+ data_size += (box->bottom - box->top - 1) * row_pitch;
+ /* fall-through */
+ case WINED3D_RTYPE_TEXTURE_1D:
+ data_size += (box->right - box->left) * resource->format->byte_count;
+ break;
+ case WINED3D_RTYPE_BUFFER:
+ data_size = box->right - box->left;
+ break;
+ case WINED3D_RTYPE_NONE:
+ break;
+ }
+
+ return data_size;
+}
+
void CDECL wined3d_resource_preload(struct wined3d_resource *resource)
{
wined3d_cs_emit_preload_resource(resource->device->cs, resource);
SIZE_T align = RESOURCE_ALIGNMENT - 1 + sizeof(*p);
void *mem;
- if (!(mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, resource->size + align)))
+ if (!(mem = heap_alloc_zero(resource->size + align)))
return FALSE;
p = (void **)(((ULONG_PTR)mem + align) & ~(RESOURCE_ALIGNMENT - 1)) - 1;
if (!p)
return;
- HeapFree(GetProcessHeap(), 0, *(--p));
+ heap_free(*(--p));
resource->heap_memory = NULL;
}
{
GLbitfield ret = 0;
- if (!(d3d_flags & WINED3D_MAP_READONLY))
+ if (d3d_flags & WINED3D_MAP_WRITE)
ret |= GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
- if (!(d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE)))
+ if (d3d_flags & WINED3D_MAP_READ)
ret |= GL_MAP_READ_BIT;
if (d3d_flags & WINED3D_MAP_DISCARD)
GLenum wined3d_resource_gl_legacy_map_flags(DWORD d3d_flags)
{
- if (d3d_flags & WINED3D_MAP_READONLY)
- return GL_READ_ONLY_ARB;
- if (d3d_flags & (WINED3D_MAP_DISCARD | WINED3D_MAP_NOOVERWRITE))
- return GL_WRITE_ONLY_ARB;
- return GL_READ_WRITE_ARB;
+ switch (d3d_flags & (WINED3D_MAP_READ | WINED3D_MAP_WRITE))
+ {
+ case WINED3D_MAP_READ:
+ return GL_READ_ONLY_ARB;
+
+ case WINED3D_MAP_WRITE:
+ return GL_WRITE_ONLY_ARB;
+
+ default:
+ return GL_READ_WRITE_ARB;
+ }
}
BOOL wined3d_resource_is_offscreen(struct wined3d_resource *resource)
void wined3d_resource_update_draw_binding(struct wined3d_resource *resource)
{
if (!wined3d_resource_is_offscreen(resource) || wined3d_settings.offscreen_rendering_mode != ORM_FBO)
+ {
resource->draw_binding = WINED3D_LOCATION_DRAWABLE;
+ }
else if (resource->multisample_type)
- resource->draw_binding = WINED3D_LOCATION_RB_MULTISAMPLE;
+ {
+ const struct wined3d_gl_info *gl_info = &resource->device->adapter->gl_info;
+ if (gl_info->supported[ARB_TEXTURE_MULTISAMPLE])
+ resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB;
+ else
+ resource->draw_binding = WINED3D_LOCATION_RB_MULTISAMPLE;
+ }
else if (resource->gl_type == WINED3D_GL_RES_TYPE_RB)
+ {
resource->draw_binding = WINED3D_LOCATION_RB_RESOLVED;
+ }
else
+ {
resource->draw_binding = WINED3D_LOCATION_TEXTURE_RGB;
+ }
}