1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2011 Joakim Sindholt <opensource@zhasha.com> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "iunknown.h" 24bf215546Sopenharmony_ci#include "surface9.h" 25bf215546Sopenharmony_ci#include "device9.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/* for marking dirty */ 28bf215546Sopenharmony_ci#include "basetexture9.h" 29bf215546Sopenharmony_ci#include "texture9.h" 30bf215546Sopenharmony_ci#include "cubetexture9.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "nine_helpers.h" 33bf215546Sopenharmony_ci#include "nine_pipe.h" 34bf215546Sopenharmony_ci#include "nine_dump.h" 35bf215546Sopenharmony_ci#include "nine_memory_helper.h" 36bf215546Sopenharmony_ci#include "nine_state.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "pipe/p_context.h" 39bf215546Sopenharmony_ci#include "pipe/p_screen.h" 40bf215546Sopenharmony_ci#include "pipe/p_state.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "util/u_math.h" 43bf215546Sopenharmony_ci#include "util/u_inlines.h" 44bf215546Sopenharmony_ci#include "util/u_surface.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#define DBG_CHANNEL DBG_SURFACE 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic void 49bf215546Sopenharmony_ciNineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ); 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ciHRESULT 52bf215546Sopenharmony_ciNineSurface9_ctor( struct NineSurface9 *This, 53bf215546Sopenharmony_ci struct NineUnknownParams *pParams, 54bf215546Sopenharmony_ci struct NineUnknown *pContainer, 55bf215546Sopenharmony_ci struct pipe_resource *pResource, 56bf215546Sopenharmony_ci struct nine_allocation *user_buffer, 57bf215546Sopenharmony_ci uint8_t TextureType, 58bf215546Sopenharmony_ci unsigned Level, 59bf215546Sopenharmony_ci unsigned Layer, 60bf215546Sopenharmony_ci D3DSURFACE_DESC *pDesc ) 61bf215546Sopenharmony_ci{ 62bf215546Sopenharmony_ci HRESULT hr; 63bf215546Sopenharmony_ci bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL; 64bf215546Sopenharmony_ci D3DMULTISAMPLE_TYPE multisample_type; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n", 67bf215546Sopenharmony_ci This, pParams->device, pResource, Level, Layer, pDesc); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci /* Mark this as a special surface held by another internal resource. */ 70bf215546Sopenharmony_ci pParams->container = pContainer; 71bf215546Sopenharmony_ci This->base.base.device = pParams->device; /* Early fill this field in case of failure */ 72bf215546Sopenharmony_ci /* Make sure there's a Desc */ 73bf215546Sopenharmony_ci assert(pDesc); 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci assert(allocate || pResource || user_buffer || 76bf215546Sopenharmony_ci pDesc->Format == D3DFMT_NULL); 77bf215546Sopenharmony_ci assert(!allocate || (!pResource && !user_buffer)); 78bf215546Sopenharmony_ci assert(!pResource || !user_buffer); 79bf215546Sopenharmony_ci assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT); 80bf215546Sopenharmony_ci assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT); 81bf215546Sopenharmony_ci /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */ 82bf215546Sopenharmony_ci assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0)); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci This->data = user_buffer; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci multisample_type = pDesc->MultiSampleType; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci /* Map MultiSampleQuality to MultiSampleType */ 89bf215546Sopenharmony_ci hr = d3dmultisample_type_check(pParams->device->screen, 90bf215546Sopenharmony_ci pDesc->Format, 91bf215546Sopenharmony_ci &multisample_type, 92bf215546Sopenharmony_ci pDesc->MultiSampleQuality, 93bf215546Sopenharmony_ci NULL); 94bf215546Sopenharmony_ci if (FAILED(hr)) { 95bf215546Sopenharmony_ci return hr; 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci /* TODO: this is (except width and height) duplicate from 99bf215546Sopenharmony_ci * container info (in the pContainer case). Some refactoring is 100bf215546Sopenharmony_ci * needed to avoid duplication */ 101bf215546Sopenharmony_ci This->base.info.screen = pParams->device->screen; 102bf215546Sopenharmony_ci This->base.info.target = PIPE_TEXTURE_2D; 103bf215546Sopenharmony_ci This->base.info.width0 = pDesc->Width; 104bf215546Sopenharmony_ci This->base.info.height0 = pDesc->Height; 105bf215546Sopenharmony_ci This->base.info.depth0 = 1; 106bf215546Sopenharmony_ci This->base.info.last_level = 0; 107bf215546Sopenharmony_ci This->base.info.array_size = 1; 108bf215546Sopenharmony_ci This->base.info.nr_samples = multisample_type; 109bf215546Sopenharmony_ci This->base.info.nr_storage_samples = multisample_type; 110bf215546Sopenharmony_ci This->base.info.usage = PIPE_USAGE_DEFAULT; 111bf215546Sopenharmony_ci This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (pDesc->Usage & D3DUSAGE_RENDERTARGET) { 114bf215546Sopenharmony_ci This->base.info.bind |= PIPE_BIND_RENDER_TARGET; 115bf215546Sopenharmony_ci } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) { 116bf215546Sopenharmony_ci if (!depth_stencil_format(pDesc->Format)) 117bf215546Sopenharmony_ci return D3DERR_INVALIDCALL; 118bf215546Sopenharmony_ci This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); 119bf215546Sopenharmony_ci if (TextureType) 120bf215546Sopenharmony_ci This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; 121bf215546Sopenharmony_ci } 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci This->base.info.flags = 0; 124bf215546Sopenharmony_ci This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen, 125bf215546Sopenharmony_ci pDesc->Format, 126bf215546Sopenharmony_ci This->base.info.target, 127bf215546Sopenharmony_ci This->base.info.nr_samples, 128bf215546Sopenharmony_ci This->base.info.bind, 129bf215546Sopenharmony_ci FALSE, 130bf215546Sopenharmony_ci pDesc->Pool == D3DPOOL_SCRATCH); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL) 133bf215546Sopenharmony_ci return D3DERR_INVALIDCALL; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if (allocate && compressed_format(pDesc->Format)) { 136bf215546Sopenharmony_ci const unsigned w = util_format_get_blockwidth(This->base.info.format); 137bf215546Sopenharmony_ci const unsigned h = util_format_get_blockheight(This->base.info.format); 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci /* Note: In the !allocate case, the test could fail (lower levels of a texture) */ 140bf215546Sopenharmony_ci user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL); 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci /* Get true format */ 144bf215546Sopenharmony_ci This->format_internal = d3d9_to_pipe_format_checked(This->base.info.screen, 145bf215546Sopenharmony_ci pDesc->Format, 146bf215546Sopenharmony_ci This->base.info.target, 147bf215546Sopenharmony_ci This->base.info.nr_samples, 148bf215546Sopenharmony_ci This->base.info.bind, 149bf215546Sopenharmony_ci FALSE, 150bf215546Sopenharmony_ci TRUE); 151bf215546Sopenharmony_ci if (This->base.info.format != This->format_internal || 152bf215546Sopenharmony_ci /* DYNAMIC Textures requires same stride as ram buffers. 153bf215546Sopenharmony_ci * The workaround stores a copy in RAM for locks. It eats more virtual space, 154bf215546Sopenharmony_ci * but that is compensated by the use of shmem */ 155bf215546Sopenharmony_ci (pParams->device->workarounds.dynamic_texture_workaround && 156bf215546Sopenharmony_ci pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { 157bf215546Sopenharmony_ci This->data_internal = nine_allocate(pParams->device->allocator, 158bf215546Sopenharmony_ci nine_format_get_level_alloc_size(This->format_internal, 159bf215546Sopenharmony_ci pDesc->Width, 160bf215546Sopenharmony_ci pDesc->Height, 161bf215546Sopenharmony_ci 0)); 162bf215546Sopenharmony_ci if (!This->data_internal) 163bf215546Sopenharmony_ci return E_OUTOFMEMORY; 164bf215546Sopenharmony_ci This->stride_internal = nine_format_get_stride(This->format_internal, 165bf215546Sopenharmony_ci pDesc->Width); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) { 169bf215546Sopenharmony_ci /* Ram buffer with no parent. Has to allocate the resource itself */ 170bf215546Sopenharmony_ci assert(!user_buffer); 171bf215546Sopenharmony_ci This->data = nine_allocate(pParams->device->allocator, 172bf215546Sopenharmony_ci nine_format_get_level_alloc_size(This->base.info.format, 173bf215546Sopenharmony_ci pDesc->Width, 174bf215546Sopenharmony_ci pDesc->Height, 175bf215546Sopenharmony_ci 0)); 176bf215546Sopenharmony_ci if (!This->data) 177bf215546Sopenharmony_ci return E_OUTOFMEMORY; 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci hr = NineResource9_ctor(&This->base, pParams, pResource, 181bf215546Sopenharmony_ci allocate && (pDesc->Pool == D3DPOOL_DEFAULT), 182bf215546Sopenharmony_ci D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage); 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci if (FAILED(hr)) 185bf215546Sopenharmony_ci return hr; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci This->transfer = NULL; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci This->texture = TextureType; 190bf215546Sopenharmony_ci This->level = Level; 191bf215546Sopenharmony_ci This->level_actual = Level; 192bf215546Sopenharmony_ci This->layer = Layer; 193bf215546Sopenharmony_ci This->desc = *pDesc; 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width); 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) 198bf215546Sopenharmony_ci This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) 201bf215546Sopenharmony_ci NineSurface9_CreatePipeSurfaces(This); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci /* TODO: investigate what else exactly needs to be cleared */ 204bf215546Sopenharmony_ci if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) 205bf215546Sopenharmony_ci nine_context_clear_render_target(pParams->device, This, 0, 0, 0, pDesc->Width, pDesc->Height); 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci NineSurface9_Dump(This); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci return D3D_OK; 210bf215546Sopenharmony_ci} 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_civoid 213bf215546Sopenharmony_ciNineSurface9_dtor( struct NineSurface9 *This ) 214bf215546Sopenharmony_ci{ 215bf215546Sopenharmony_ci bool is_worker = nine_context_is_worker(This->base.base.device); 216bf215546Sopenharmony_ci DBG("This=%p\n", This); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci if (This->transfer) { 219bf215546Sopenharmony_ci struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device); 220bf215546Sopenharmony_ci pipe->texture_unmap(pipe, This->transfer); 221bf215546Sopenharmony_ci This->transfer = NULL; 222bf215546Sopenharmony_ci } 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci /* Note: Following condition cannot happen currently, since we 225bf215546Sopenharmony_ci * refcount the surface in the functions increasing 226bf215546Sopenharmony_ci * pending_uploads_counter. */ 227bf215546Sopenharmony_ci if (p_atomic_read(&This->pending_uploads_counter)) 228bf215546Sopenharmony_ci nine_csmt_process(This->base.base.device); 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci pipe_surface_reference(&This->surface[0], NULL); 231bf215546Sopenharmony_ci pipe_surface_reference(&This->surface[1], NULL); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (!is_worker && This->lock_count && (This->data_internal || This->data)) { 234bf215546Sopenharmony_ci /* For is_worker nine_free_worker will handle it */ 235bf215546Sopenharmony_ci nine_pointer_strongrelease(This->base.base.device->allocator, 236bf215546Sopenharmony_ci This->data_internal ? This->data_internal : This->data); 237bf215546Sopenharmony_ci } 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci /* Release system memory when we have to manage it (no parent) */ 240bf215546Sopenharmony_ci if (This->data) { 241bf215546Sopenharmony_ci if (is_worker) 242bf215546Sopenharmony_ci nine_free_worker(This->base.base.device->allocator, This->data); 243bf215546Sopenharmony_ci else 244bf215546Sopenharmony_ci nine_free(This->base.base.device->allocator, This->data); 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci if (This->data_internal) { 247bf215546Sopenharmony_ci if (is_worker) 248bf215546Sopenharmony_ci nine_free_worker(This->base.base.device->allocator, This->data_internal); 249bf215546Sopenharmony_ci else 250bf215546Sopenharmony_ci nine_free(This->base.base.device->allocator, This->data_internal); 251bf215546Sopenharmony_ci } 252bf215546Sopenharmony_ci NineResource9_dtor(&This->base); 253bf215546Sopenharmony_ci} 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_cistatic void 256bf215546Sopenharmony_ciNineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ) 257bf215546Sopenharmony_ci{ 258bf215546Sopenharmony_ci struct pipe_context *pipe; 259bf215546Sopenharmony_ci struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); 260bf215546Sopenharmony_ci struct pipe_resource *resource = This->base.resource; 261bf215546Sopenharmony_ci struct pipe_surface templ; 262bf215546Sopenharmony_ci enum pipe_format srgb_format; 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci assert(This->desc.Pool == D3DPOOL_DEFAULT); 265bf215546Sopenharmony_ci assert(resource); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci srgb_format = util_format_srgb(resource->format); 268bf215546Sopenharmony_ci if (srgb_format == PIPE_FORMAT_NONE || 269bf215546Sopenharmony_ci !screen->is_format_supported(screen, srgb_format, 270bf215546Sopenharmony_ci resource->target, 0, 0, resource->bind)) 271bf215546Sopenharmony_ci srgb_format = resource->format; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 274bf215546Sopenharmony_ci templ.format = resource->format; 275bf215546Sopenharmony_ci templ.u.tex.level = This->level; 276bf215546Sopenharmony_ci templ.u.tex.first_layer = This->layer; 277bf215546Sopenharmony_ci templ.u.tex.last_layer = This->layer; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci pipe = nine_context_get_pipe_acquire(This->base.base.device); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci This->surface[0] = pipe->create_surface(pipe, resource, &templ); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci memset(&templ, 0, sizeof(templ)); 284bf215546Sopenharmony_ci templ.format = srgb_format; 285bf215546Sopenharmony_ci templ.u.tex.level = This->level; 286bf215546Sopenharmony_ci templ.u.tex.first_layer = This->layer; 287bf215546Sopenharmony_ci templ.u.tex.last_layer = This->layer; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci This->surface[1] = pipe->create_surface(pipe, resource, &templ); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci nine_context_get_pipe_release(This->base.base.device); 292bf215546Sopenharmony_ci 293bf215546Sopenharmony_ci assert(This->surface[0]); /* TODO: Handle failure */ 294bf215546Sopenharmony_ci assert(This->surface[1]); 295bf215546Sopenharmony_ci} 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci#if defined(DEBUG) || !defined(NDEBUG) 298bf215546Sopenharmony_civoid 299bf215546Sopenharmony_ciNineSurface9_Dump( struct NineSurface9 *This ) 300bf215546Sopenharmony_ci{ 301bf215546Sopenharmony_ci struct NineBaseTexture9 *tex; 302bf215546Sopenharmony_ci GUID id = IID_IDirect3DBaseTexture9; 303bf215546Sopenharmony_ci REFIID ref = &id; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n" 306bf215546Sopenharmony_ci "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n" 307bf215546Sopenharmony_ci "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data, 308bf215546Sopenharmony_ci nine_D3DPOOL_to_str(This->desc.Pool), 309bf215546Sopenharmony_ci nine_D3DRTYPE_to_str(This->desc.Type), 310bf215546Sopenharmony_ci nine_D3DUSAGE_to_str(This->desc.Usage), 311bf215546Sopenharmony_ci This->desc.Width, This->desc.Height, 312bf215546Sopenharmony_ci d3dformat_to_string(This->desc.Format), This->stride, 313bf215546Sopenharmony_ci This->base.resource && 314bf215546Sopenharmony_ci (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE), 315bf215546Sopenharmony_ci This->level, This->level_actual, This->layer); 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if (!This->base.base.container) 318bf215546Sopenharmony_ci return; 319bf215546Sopenharmony_ci NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex); 320bf215546Sopenharmony_ci if (tex) { 321bf215546Sopenharmony_ci NineBaseTexture9_Dump(tex); 322bf215546Sopenharmony_ci NineUnknown_Release(NineUnknown(tex)); 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci} 325bf215546Sopenharmony_ci#endif /* DEBUG || !NDEBUG */ 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ciHRESULT NINE_WINAPI 328bf215546Sopenharmony_ciNineSurface9_GetContainer( struct NineSurface9 *This, 329bf215546Sopenharmony_ci REFIID riid, 330bf215546Sopenharmony_ci void **ppContainer ) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci HRESULT hr; 333bf215546Sopenharmony_ci char guid_str[64]; 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci DBG("This=%p riid=%p id=%s ppContainer=%p\n", 336bf215546Sopenharmony_ci This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci (void)guid_str; 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (!ppContainer) return E_POINTER; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci /* Use device for OffscreenPlainSurface, DepthStencilSurface and RenderTarget */ 343bf215546Sopenharmony_ci hr = NineUnknown_QueryInterface(NineUnknown(This)->container ? 344bf215546Sopenharmony_ci NineUnknown(This)->container : &NineUnknown(This)->device->base, 345bf215546Sopenharmony_ci riid, ppContainer); 346bf215546Sopenharmony_ci if (FAILED(hr)) 347bf215546Sopenharmony_ci DBG("QueryInterface FAILED!\n"); 348bf215546Sopenharmony_ci return hr; 349bf215546Sopenharmony_ci} 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_civoid 352bf215546Sopenharmony_ciNineSurface9_MarkContainerDirty( struct NineSurface9 *This ) 353bf215546Sopenharmony_ci{ 354bf215546Sopenharmony_ci if (This->texture) { 355bf215546Sopenharmony_ci struct NineBaseTexture9 *tex = 356bf215546Sopenharmony_ci NineBaseTexture9(This->base.base.container); 357bf215546Sopenharmony_ci assert(tex); 358bf215546Sopenharmony_ci assert(This->texture == D3DRTYPE_TEXTURE || 359bf215546Sopenharmony_ci This->texture == D3DRTYPE_CUBETEXTURE); 360bf215546Sopenharmony_ci if (This->base.pool == D3DPOOL_MANAGED) 361bf215546Sopenharmony_ci tex->managed.dirty = TRUE; 362bf215546Sopenharmony_ci else 363bf215546Sopenharmony_ci if (This->base.usage & D3DUSAGE_AUTOGENMIPMAP) 364bf215546Sopenharmony_ci tex->dirty_mip = TRUE; 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci BASETEX_REGISTER_UPDATE(tex); 367bf215546Sopenharmony_ci } 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ciHRESULT NINE_WINAPI 371bf215546Sopenharmony_ciNineSurface9_GetDesc( struct NineSurface9 *This, 372bf215546Sopenharmony_ci D3DSURFACE_DESC *pDesc ) 373bf215546Sopenharmony_ci{ 374bf215546Sopenharmony_ci user_assert(pDesc != NULL, E_POINTER); 375bf215546Sopenharmony_ci DBG("This=%p pDesc=%p\n", This, pDesc); 376bf215546Sopenharmony_ci *pDesc = This->desc; 377bf215546Sopenharmony_ci return D3D_OK; 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci/* Add the dirty rects to the source texture */ 381bf215546Sopenharmony_ciinline void 382bf215546Sopenharmony_ciNineSurface9_AddDirtyRect( struct NineSurface9 *This, 383bf215546Sopenharmony_ci const struct pipe_box *box ) 384bf215546Sopenharmony_ci{ 385bf215546Sopenharmony_ci RECT dirty_rect; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci DBG("This=%p box=%p\n", This, box); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci assert (This->base.pool != D3DPOOL_MANAGED || 390bf215546Sopenharmony_ci This->texture == D3DRTYPE_CUBETEXTURE || 391bf215546Sopenharmony_ci This->texture == D3DRTYPE_TEXTURE); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (This->base.pool == D3DPOOL_DEFAULT) 394bf215546Sopenharmony_ci return; 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_ci /* Add a dirty rect to level 0 of the parent texture */ 397bf215546Sopenharmony_ci dirty_rect.left = box->x << This->level_actual; 398bf215546Sopenharmony_ci dirty_rect.right = dirty_rect.left + (box->width << This->level_actual); 399bf215546Sopenharmony_ci dirty_rect.top = box->y << This->level_actual; 400bf215546Sopenharmony_ci dirty_rect.bottom = dirty_rect.top + (box->height << This->level_actual); 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci if (This->texture == D3DRTYPE_TEXTURE) { 403bf215546Sopenharmony_ci struct NineTexture9 *tex = 404bf215546Sopenharmony_ci NineTexture9(This->base.base.container); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci NineTexture9_AddDirtyRect(tex, &dirty_rect); 407bf215546Sopenharmony_ci } else if (This->texture == D3DRTYPE_CUBETEXTURE) { 408bf215546Sopenharmony_ci struct NineCubeTexture9 *ctex = 409bf215546Sopenharmony_ci NineCubeTexture9(This->base.base.container); 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci NineCubeTexture9_AddDirtyRect(ctex, This->layer, &dirty_rect); 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci} 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_cistatic inline unsigned 416bf215546Sopenharmony_ciNineSurface9_GetSystemMemOffset(enum pipe_format format, unsigned stride, 417bf215546Sopenharmony_ci int x, int y) 418bf215546Sopenharmony_ci{ 419bf215546Sopenharmony_ci unsigned x_offset = util_format_get_stride(format, x); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci y = util_format_get_nblocksy(format, y); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci return y * stride + x_offset; 424bf215546Sopenharmony_ci} 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ciHRESULT NINE_WINAPI 427bf215546Sopenharmony_ciNineSurface9_LockRect( struct NineSurface9 *This, 428bf215546Sopenharmony_ci D3DLOCKED_RECT *pLockedRect, 429bf215546Sopenharmony_ci const RECT *pRect, 430bf215546Sopenharmony_ci DWORD Flags ) 431bf215546Sopenharmony_ci{ 432bf215546Sopenharmony_ci struct pipe_resource *resource = This->base.resource; 433bf215546Sopenharmony_ci struct pipe_context *pipe; 434bf215546Sopenharmony_ci struct pipe_box box; 435bf215546Sopenharmony_ci unsigned usage; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci DBG("This=%p pLockedRect=%p pRect=%p[%u..%u,%u..%u] Flags=%s\n", This, 438bf215546Sopenharmony_ci pLockedRect, pRect, 439bf215546Sopenharmony_ci pRect ? pRect->left : 0, pRect ? pRect->right : 0, 440bf215546Sopenharmony_ci pRect ? pRect->top : 0, pRect ? pRect->bottom : 0, 441bf215546Sopenharmony_ci nine_D3DLOCK_to_str(Flags)); 442bf215546Sopenharmony_ci NineSurface9_Dump(This); 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci /* check if it's already locked */ 445bf215546Sopenharmony_ci user_assert(This->lock_count == 0, D3DERR_INVALIDCALL); 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci /* set pBits to NULL after lock_count check */ 448bf215546Sopenharmony_ci user_assert(pLockedRect, E_POINTER); 449bf215546Sopenharmony_ci pLockedRect->pBits = NULL; 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci#ifdef NINE_STRICT 452bf215546Sopenharmony_ci user_assert(This->base.pool != D3DPOOL_DEFAULT || 453bf215546Sopenharmony_ci (resource && (resource->flags & NINE_RESOURCE_FLAG_LOCKABLE)), 454bf215546Sopenharmony_ci D3DERR_INVALIDCALL); 455bf215546Sopenharmony_ci#endif 456bf215546Sopenharmony_ci user_assert(!((Flags & D3DLOCK_DISCARD) && (Flags & D3DLOCK_READONLY)), 457bf215546Sopenharmony_ci D3DERR_INVALIDCALL); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci user_assert(This->desc.MultiSampleType == D3DMULTISAMPLE_NONE, 460bf215546Sopenharmony_ci D3DERR_INVALIDCALL); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci if (pRect && This->desc.Pool == D3DPOOL_DEFAULT && 463bf215546Sopenharmony_ci util_format_is_compressed(This->base.info.format)) { 464bf215546Sopenharmony_ci const unsigned w = util_format_get_blockwidth(This->base.info.format); 465bf215546Sopenharmony_ci const unsigned h = util_format_get_blockheight(This->base.info.format); 466bf215546Sopenharmony_ci user_assert((pRect->left == 0 && pRect->right == This->desc.Width && 467bf215546Sopenharmony_ci pRect->top == 0 && pRect->bottom == This->desc.Height) || 468bf215546Sopenharmony_ci (!(pRect->left % w) && !(pRect->right % w) && 469bf215546Sopenharmony_ci !(pRect->top % h) && !(pRect->bottom % h)), 470bf215546Sopenharmony_ci D3DERR_INVALIDCALL); 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci if (Flags & D3DLOCK_DISCARD) { 474bf215546Sopenharmony_ci usage = PIPE_MAP_WRITE | PIPE_MAP_DISCARD_RANGE; 475bf215546Sopenharmony_ci } else { 476bf215546Sopenharmony_ci usage = (Flags & D3DLOCK_READONLY) ? 477bf215546Sopenharmony_ci PIPE_MAP_READ : PIPE_MAP_READ_WRITE; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci if (Flags & D3DLOCK_DONOTWAIT) 480bf215546Sopenharmony_ci usage |= PIPE_MAP_DONTBLOCK; 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (pRect) { 483bf215546Sopenharmony_ci /* Windows XP accepts invalid locking rectangles, Windows 7 rejects 484bf215546Sopenharmony_ci * them. Use Windows XP behaviour for now. */ 485bf215546Sopenharmony_ci rect_to_pipe_box(&box, pRect); 486bf215546Sopenharmony_ci } else { 487bf215546Sopenharmony_ci u_box_origin_2d(This->desc.Width, This->desc.Height, &box); 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci box.z = This->layer; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci user_warn(This->desc.Format == D3DFMT_NULL); 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci if (p_atomic_read(&This->pending_uploads_counter)) 494bf215546Sopenharmony_ci nine_csmt_process(This->base.base.device); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci if (This->data_internal || This->data) { 497bf215546Sopenharmony_ci enum pipe_format format = This->base.info.format; 498bf215546Sopenharmony_ci unsigned stride = This->stride; 499bf215546Sopenharmony_ci uint8_t *data = nine_get_pointer(This->base.base.device->allocator, This->data_internal ? This->data_internal : This->data); 500bf215546Sopenharmony_ci if (This->data_internal) { 501bf215546Sopenharmony_ci format = This->format_internal; 502bf215546Sopenharmony_ci stride = This->stride_internal; 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci /* ATI1 and ATI2 need special handling, because of d3d9 bug. 505bf215546Sopenharmony_ci * We must advertise to the application as if it is uncompressed 506bf215546Sopenharmony_ci * and bpp 8, and the app has a workaround to work with the fact 507bf215546Sopenharmony_ci * that it is actually compressed. */ 508bf215546Sopenharmony_ci if (is_ATI1_ATI2(format)) { 509bf215546Sopenharmony_ci pLockedRect->Pitch = This->desc.Width; 510bf215546Sopenharmony_ci pLockedRect->pBits = data + box.y * This->desc.Width + box.x; 511bf215546Sopenharmony_ci } else { 512bf215546Sopenharmony_ci pLockedRect->Pitch = stride; 513bf215546Sopenharmony_ci pLockedRect->pBits = data + 514bf215546Sopenharmony_ci NineSurface9_GetSystemMemOffset(format, 515bf215546Sopenharmony_ci stride, 516bf215546Sopenharmony_ci box.x, 517bf215546Sopenharmony_ci box.y); 518bf215546Sopenharmony_ci } 519bf215546Sopenharmony_ci DBG("returning system memory %p\n", pLockedRect->pBits); 520bf215546Sopenharmony_ci } else { 521bf215546Sopenharmony_ci bool no_refs = !p_atomic_read(&This->base.base.bind) && 522bf215546Sopenharmony_ci !(This->base.base.container && p_atomic_read(&This->base.base.container->bind)); 523bf215546Sopenharmony_ci DBG("mapping pipe_resource %p (level=%u usage=%x)\n", 524bf215546Sopenharmony_ci resource, This->level, usage); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci /* if the object is not bound internally, there can't be any pending 527bf215546Sopenharmony_ci * operation with the surface in the queue */ 528bf215546Sopenharmony_ci if (no_refs) 529bf215546Sopenharmony_ci pipe = nine_context_get_pipe_acquire(This->base.base.device); 530bf215546Sopenharmony_ci else 531bf215546Sopenharmony_ci pipe = NineDevice9_GetPipe(This->base.base.device); 532bf215546Sopenharmony_ci pLockedRect->pBits = pipe->texture_map(pipe, resource, 533bf215546Sopenharmony_ci This->level, usage, &box, 534bf215546Sopenharmony_ci &This->transfer); 535bf215546Sopenharmony_ci if (no_refs) 536bf215546Sopenharmony_ci nine_context_get_pipe_release(This->base.base.device); 537bf215546Sopenharmony_ci if (!This->transfer) { 538bf215546Sopenharmony_ci DBG("texture_map failed\n"); 539bf215546Sopenharmony_ci if (Flags & D3DLOCK_DONOTWAIT) 540bf215546Sopenharmony_ci return D3DERR_WASSTILLDRAWING; 541bf215546Sopenharmony_ci return D3DERR_INVALIDCALL; 542bf215546Sopenharmony_ci } 543bf215546Sopenharmony_ci pLockedRect->Pitch = This->transfer->stride; 544bf215546Sopenharmony_ci } 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci if (!(Flags & (D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_READONLY))) { 547bf215546Sopenharmony_ci NineSurface9_MarkContainerDirty(This); 548bf215546Sopenharmony_ci NineSurface9_AddDirtyRect(This, &box); 549bf215546Sopenharmony_ci } 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci ++This->lock_count; 552bf215546Sopenharmony_ci return D3D_OK; 553bf215546Sopenharmony_ci} 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ciHRESULT NINE_WINAPI 556bf215546Sopenharmony_ciNineSurface9_UnlockRect( struct NineSurface9 *This ) 557bf215546Sopenharmony_ci{ 558bf215546Sopenharmony_ci struct pipe_box dst_box, src_box; 559bf215546Sopenharmony_ci struct pipe_context *pipe; 560bf215546Sopenharmony_ci DBG("This=%p lock_count=%u\n", This, This->lock_count); 561bf215546Sopenharmony_ci user_assert(This->lock_count, D3DERR_INVALIDCALL); 562bf215546Sopenharmony_ci if (This->transfer) { 563bf215546Sopenharmony_ci pipe = nine_context_get_pipe_acquire(This->base.base.device); 564bf215546Sopenharmony_ci pipe->texture_unmap(pipe, This->transfer); 565bf215546Sopenharmony_ci nine_context_get_pipe_release(This->base.base.device); 566bf215546Sopenharmony_ci This->transfer = NULL; 567bf215546Sopenharmony_ci } 568bf215546Sopenharmony_ci --This->lock_count; 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci if (This->data_internal) { 571bf215546Sopenharmony_ci nine_pointer_weakrelease(This->base.base.device->allocator, This->data_internal); 572bf215546Sopenharmony_ci if (This->data) { 573bf215546Sopenharmony_ci (void) util_format_translate(This->base.info.format, 574bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, This->data), 575bf215546Sopenharmony_ci This->stride, 576bf215546Sopenharmony_ci 0, 0, 577bf215546Sopenharmony_ci This->format_internal, 578bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, This->data_internal), 579bf215546Sopenharmony_ci This->stride_internal, 580bf215546Sopenharmony_ci 0, 0, 581bf215546Sopenharmony_ci This->desc.Width, This->desc.Height); 582bf215546Sopenharmony_ci nine_pointer_weakrelease(This->base.base.device->allocator, This->data); 583bf215546Sopenharmony_ci nine_pointer_strongrelease(This->base.base.device->allocator, This->data_internal); 584bf215546Sopenharmony_ci } else { 585bf215546Sopenharmony_ci u_box_2d_zslice(0, 0, This->layer, 586bf215546Sopenharmony_ci This->desc.Width, This->desc.Height, &dst_box); 587bf215546Sopenharmony_ci u_box_2d_zslice(0, 0, 0, 588bf215546Sopenharmony_ci This->desc.Width, This->desc.Height, &src_box); 589bf215546Sopenharmony_ci 590bf215546Sopenharmony_ci nine_context_box_upload(This->base.base.device, 591bf215546Sopenharmony_ci &This->pending_uploads_counter, 592bf215546Sopenharmony_ci (struct NineUnknown *)This, 593bf215546Sopenharmony_ci This->base.resource, 594bf215546Sopenharmony_ci This->level, 595bf215546Sopenharmony_ci &dst_box, 596bf215546Sopenharmony_ci This->format_internal, 597bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, This->data_internal), 598bf215546Sopenharmony_ci This->stride_internal, 599bf215546Sopenharmony_ci 0, /* depth = 1 */ 600bf215546Sopenharmony_ci &src_box); 601bf215546Sopenharmony_ci nine_pointer_delayedstrongrelease(This->base.base.device->allocator, This->data_internal, &This->pending_uploads_counter); 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci } else if (This->data) { 604bf215546Sopenharmony_ci nine_pointer_weakrelease(This->base.base.device->allocator, This->data); 605bf215546Sopenharmony_ci } 606bf215546Sopenharmony_ci 607bf215546Sopenharmony_ci return D3D_OK; 608bf215546Sopenharmony_ci} 609bf215546Sopenharmony_ci 610bf215546Sopenharmony_ciHRESULT NINE_WINAPI 611bf215546Sopenharmony_ciNineSurface9_GetDC( struct NineSurface9 *This, 612bf215546Sopenharmony_ci HDC *phdc ) 613bf215546Sopenharmony_ci{ 614bf215546Sopenharmony_ci STUB(D3DERR_INVALIDCALL); 615bf215546Sopenharmony_ci} 616bf215546Sopenharmony_ci 617bf215546Sopenharmony_ciHRESULT NINE_WINAPI 618bf215546Sopenharmony_ciNineSurface9_ReleaseDC( struct NineSurface9 *This, 619bf215546Sopenharmony_ci HDC hdc ) 620bf215546Sopenharmony_ci{ 621bf215546Sopenharmony_ci STUB(D3DERR_INVALIDCALL); 622bf215546Sopenharmony_ci} 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ciIDirect3DSurface9Vtbl NineSurface9_vtable = { 625bf215546Sopenharmony_ci (void *)NineUnknown_QueryInterface, 626bf215546Sopenharmony_ci (void *)NineUnknown_AddRef, 627bf215546Sopenharmony_ci (void *)NineUnknown_Release, 628bf215546Sopenharmony_ci (void *)NineUnknown_GetDevice, /* actually part of Resource9 iface */ 629bf215546Sopenharmony_ci (void *)NineUnknown_SetPrivateData, 630bf215546Sopenharmony_ci (void *)NineUnknown_GetPrivateData, 631bf215546Sopenharmony_ci (void *)NineUnknown_FreePrivateData, 632bf215546Sopenharmony_ci (void *)NineResource9_SetPriority, 633bf215546Sopenharmony_ci (void *)NineResource9_GetPriority, 634bf215546Sopenharmony_ci (void *)NineResource9_PreLoad, 635bf215546Sopenharmony_ci (void *)NineResource9_GetType, 636bf215546Sopenharmony_ci (void *)NineSurface9_GetContainer, 637bf215546Sopenharmony_ci (void *)NineSurface9_GetDesc, 638bf215546Sopenharmony_ci (void *)NineSurface9_LockRect, 639bf215546Sopenharmony_ci (void *)NineSurface9_UnlockRect, 640bf215546Sopenharmony_ci (void *)NineSurface9_GetDC, 641bf215546Sopenharmony_ci (void *)NineSurface9_ReleaseDC 642bf215546Sopenharmony_ci}; 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_ci/* When this function is called, we have already checked 645bf215546Sopenharmony_ci * The copy regions fit the surfaces */ 646bf215546Sopenharmony_civoid 647bf215546Sopenharmony_ciNineSurface9_CopyMemToDefault( struct NineSurface9 *This, 648bf215546Sopenharmony_ci struct NineSurface9 *From, 649bf215546Sopenharmony_ci const POINT *pDestPoint, 650bf215546Sopenharmony_ci const RECT *pSourceRect ) 651bf215546Sopenharmony_ci{ 652bf215546Sopenharmony_ci struct pipe_resource *r_dst = This->base.resource; 653bf215546Sopenharmony_ci struct pipe_box dst_box, src_box; 654bf215546Sopenharmony_ci int src_x, src_y, dst_x, dst_y, copy_width, copy_height; 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_DEFAULT && 657bf215546Sopenharmony_ci From->base.pool == D3DPOOL_SYSTEMMEM); 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ci if (pDestPoint) { 660bf215546Sopenharmony_ci dst_x = pDestPoint->x; 661bf215546Sopenharmony_ci dst_y = pDestPoint->y; 662bf215546Sopenharmony_ci } else { 663bf215546Sopenharmony_ci dst_x = 0; 664bf215546Sopenharmony_ci dst_y = 0; 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci if (pSourceRect) { 668bf215546Sopenharmony_ci src_x = pSourceRect->left; 669bf215546Sopenharmony_ci src_y = pSourceRect->top; 670bf215546Sopenharmony_ci copy_width = pSourceRect->right - pSourceRect->left; 671bf215546Sopenharmony_ci copy_height = pSourceRect->bottom - pSourceRect->top; 672bf215546Sopenharmony_ci } else { 673bf215546Sopenharmony_ci src_x = 0; 674bf215546Sopenharmony_ci src_y = 0; 675bf215546Sopenharmony_ci copy_width = From->desc.Width; 676bf215546Sopenharmony_ci copy_height = From->desc.Height; 677bf215546Sopenharmony_ci } 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci u_box_2d_zslice(dst_x, dst_y, This->layer, 680bf215546Sopenharmony_ci copy_width, copy_height, &dst_box); 681bf215546Sopenharmony_ci u_box_2d_zslice(src_x, src_y, 0, 682bf215546Sopenharmony_ci copy_width, copy_height, &src_box); 683bf215546Sopenharmony_ci 684bf215546Sopenharmony_ci if (This->data_internal) { 685bf215546Sopenharmony_ci (void) util_format_translate(This->format_internal, 686bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, This->data_internal), 687bf215546Sopenharmony_ci This->stride_internal, 688bf215546Sopenharmony_ci dst_x, dst_y, 689bf215546Sopenharmony_ci From->base.info.format, 690bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, From->data), 691bf215546Sopenharmony_ci From->stride, 692bf215546Sopenharmony_ci src_x, src_y, 693bf215546Sopenharmony_ci copy_width, copy_height); 694bf215546Sopenharmony_ci nine_pointer_weakrelease(This->base.base.device->allocator, From->data); 695bf215546Sopenharmony_ci nine_pointer_strongrelease(This->base.base.device->allocator, This->data_internal); 696bf215546Sopenharmony_ci } 697bf215546Sopenharmony_ci 698bf215546Sopenharmony_ci nine_context_box_upload(This->base.base.device, 699bf215546Sopenharmony_ci &From->pending_uploads_counter, 700bf215546Sopenharmony_ci (struct NineUnknown *)From, 701bf215546Sopenharmony_ci r_dst, 702bf215546Sopenharmony_ci This->level, 703bf215546Sopenharmony_ci &dst_box, 704bf215546Sopenharmony_ci From->base.info.format, 705bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, From->data), 706bf215546Sopenharmony_ci From->stride, 707bf215546Sopenharmony_ci 0, /* depth = 1 */ 708bf215546Sopenharmony_ci &src_box); 709bf215546Sopenharmony_ci nine_pointer_delayedstrongrelease(This->base.base.device->allocator, From->data, &From->pending_uploads_counter); 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci if (From->texture == D3DRTYPE_TEXTURE) { 712bf215546Sopenharmony_ci struct NineTexture9 *tex = 713bf215546Sopenharmony_ci NineTexture9(From->base.base.container); 714bf215546Sopenharmony_ci /* D3DPOOL_SYSTEMMEM with buffer content passed 715bf215546Sopenharmony_ci * from the user: execute the upload right now. 716bf215546Sopenharmony_ci * It is possible it is enough to delay upload 717bf215546Sopenharmony_ci * until the surface refcount is 0, but the 718bf215546Sopenharmony_ci * bind refcount may not be 0, and thus the dtor 719bf215546Sopenharmony_ci * is not executed (and doesn't trigger the 720bf215546Sopenharmony_ci * pending_uploads_counter check). */ 721bf215546Sopenharmony_ci if (!tex->managed_buffer) 722bf215546Sopenharmony_ci nine_csmt_process(This->base.base.device); 723bf215546Sopenharmony_ci } 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci NineSurface9_MarkContainerDirty(This); 726bf215546Sopenharmony_ci} 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_civoid 729bf215546Sopenharmony_ciNineSurface9_CopyDefaultToMem( struct NineSurface9 *This, 730bf215546Sopenharmony_ci struct NineSurface9 *From ) 731bf215546Sopenharmony_ci{ 732bf215546Sopenharmony_ci struct pipe_context *pipe; 733bf215546Sopenharmony_ci struct pipe_resource *r_src = From->base.resource; 734bf215546Sopenharmony_ci struct pipe_transfer *transfer; 735bf215546Sopenharmony_ci struct pipe_box src_box; 736bf215546Sopenharmony_ci uint8_t *p_dst; 737bf215546Sopenharmony_ci const uint8_t *p_src; 738bf215546Sopenharmony_ci 739bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_SYSTEMMEM && 740bf215546Sopenharmony_ci From->base.pool == D3DPOOL_DEFAULT); 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci assert(This->desc.Width == From->desc.Width); 743bf215546Sopenharmony_ci assert(This->desc.Height == From->desc.Height); 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci u_box_origin_2d(This->desc.Width, This->desc.Height, &src_box); 746bf215546Sopenharmony_ci src_box.z = From->layer; 747bf215546Sopenharmony_ci 748bf215546Sopenharmony_ci if (p_atomic_read(&This->pending_uploads_counter)) 749bf215546Sopenharmony_ci nine_csmt_process(This->base.base.device); 750bf215546Sopenharmony_ci 751bf215546Sopenharmony_ci pipe = NineDevice9_GetPipe(This->base.base.device); 752bf215546Sopenharmony_ci p_src = pipe->texture_map(pipe, r_src, From->level, 753bf215546Sopenharmony_ci PIPE_MAP_READ, 754bf215546Sopenharmony_ci &src_box, &transfer); 755bf215546Sopenharmony_ci p_dst = nine_get_pointer(This->base.base.device->allocator, This->data); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci assert (p_src && p_dst); 758bf215546Sopenharmony_ci 759bf215546Sopenharmony_ci util_copy_rect(p_dst, This->base.info.format, 760bf215546Sopenharmony_ci This->stride, 0, 0, 761bf215546Sopenharmony_ci This->desc.Width, This->desc.Height, 762bf215546Sopenharmony_ci p_src, 763bf215546Sopenharmony_ci transfer->stride, 0, 0); 764bf215546Sopenharmony_ci 765bf215546Sopenharmony_ci pipe->texture_unmap(pipe, transfer); 766bf215546Sopenharmony_ci 767bf215546Sopenharmony_ci nine_pointer_weakrelease(This->base.base.device->allocator, This->data); 768bf215546Sopenharmony_ci} 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci/* Gladly, rendering to a MANAGED surface is not permitted, so we will 772bf215546Sopenharmony_ci * never have to do the reverse, i.e. download the surface. 773bf215546Sopenharmony_ci */ 774bf215546Sopenharmony_ciHRESULT 775bf215546Sopenharmony_ciNineSurface9_UploadSelf( struct NineSurface9 *This, 776bf215546Sopenharmony_ci const struct pipe_box *damaged ) 777bf215546Sopenharmony_ci{ 778bf215546Sopenharmony_ci struct pipe_resource *res = This->base.resource; 779bf215546Sopenharmony_ci struct pipe_box box; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci DBG("This=%p damaged=%p\n", This, damaged); 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_MANAGED); 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci if (damaged) { 786bf215546Sopenharmony_ci box = *damaged; 787bf215546Sopenharmony_ci box.z = This->layer; 788bf215546Sopenharmony_ci box.depth = 1; 789bf215546Sopenharmony_ci } else { 790bf215546Sopenharmony_ci box.x = 0; 791bf215546Sopenharmony_ci box.y = 0; 792bf215546Sopenharmony_ci box.z = This->layer; 793bf215546Sopenharmony_ci box.width = This->desc.Width; 794bf215546Sopenharmony_ci box.height = This->desc.Height; 795bf215546Sopenharmony_ci box.depth = 1; 796bf215546Sopenharmony_ci } 797bf215546Sopenharmony_ci 798bf215546Sopenharmony_ci nine_context_box_upload(This->base.base.device, 799bf215546Sopenharmony_ci &This->pending_uploads_counter, 800bf215546Sopenharmony_ci (struct NineUnknown *)This, 801bf215546Sopenharmony_ci res, 802bf215546Sopenharmony_ci This->level, 803bf215546Sopenharmony_ci &box, 804bf215546Sopenharmony_ci res->format, 805bf215546Sopenharmony_ci nine_get_pointer(This->base.base.device->allocator, This->data), 806bf215546Sopenharmony_ci This->stride, 807bf215546Sopenharmony_ci 0, /* depth = 1 */ 808bf215546Sopenharmony_ci &box); 809bf215546Sopenharmony_ci nine_pointer_delayedstrongrelease(This->base.base.device->allocator, This->data, &This->pending_uploads_counter); 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci return D3D_OK; 812bf215546Sopenharmony_ci} 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci/* Currently nine_context uses the NineSurface9 815bf215546Sopenharmony_ci * fields when it is render target. Any modification requires 816bf215546Sopenharmony_ci * pending commands with the surface to be executed. If the bind 817bf215546Sopenharmony_ci * count is 0, there is no pending commands. */ 818bf215546Sopenharmony_ci#define PROCESS_IF_BOUND(surf) \ 819bf215546Sopenharmony_ci if (surf->base.base.bind) \ 820bf215546Sopenharmony_ci nine_csmt_process(surf->base.base.device); 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_civoid 823bf215546Sopenharmony_ciNineSurface9_SetResource( struct NineSurface9 *This, 824bf215546Sopenharmony_ci struct pipe_resource *resource, unsigned level ) 825bf215546Sopenharmony_ci{ 826bf215546Sopenharmony_ci /* No need to call PROCESS_IF_BOUND, because SetResource is used only 827bf215546Sopenharmony_ci * for MANAGED textures, and they are not render targets. */ 828bf215546Sopenharmony_ci assert(This->base.pool == D3DPOOL_MANAGED); 829bf215546Sopenharmony_ci This->level = level; 830bf215546Sopenharmony_ci pipe_resource_reference(&This->base.resource, resource); 831bf215546Sopenharmony_ci} 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_civoid 834bf215546Sopenharmony_ciNineSurface9_SetMultiSampleType( struct NineSurface9 *This, 835bf215546Sopenharmony_ci D3DMULTISAMPLE_TYPE mst ) 836bf215546Sopenharmony_ci{ 837bf215546Sopenharmony_ci PROCESS_IF_BOUND(This); 838bf215546Sopenharmony_ci This->desc.MultiSampleType = mst; 839bf215546Sopenharmony_ci} 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_civoid 842bf215546Sopenharmony_ciNineSurface9_SetResourceResize( struct NineSurface9 *This, 843bf215546Sopenharmony_ci struct pipe_resource *resource ) 844bf215546Sopenharmony_ci{ 845bf215546Sopenharmony_ci assert(This->level == 0 && This->level_actual == 0); 846bf215546Sopenharmony_ci assert(!This->lock_count); 847bf215546Sopenharmony_ci assert(This->desc.Pool == D3DPOOL_DEFAULT); 848bf215546Sopenharmony_ci assert(!This->texture); 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_ci PROCESS_IF_BOUND(This); 851bf215546Sopenharmony_ci pipe_resource_reference(&This->base.resource, resource); 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci This->desc.Width = This->base.info.width0 = resource->width0; 854bf215546Sopenharmony_ci This->desc.Height = This->base.info.height0 = resource->height0; 855bf215546Sopenharmony_ci This->base.info.nr_samples = resource->nr_samples; 856bf215546Sopenharmony_ci This->base.info.nr_storage_samples = resource->nr_storage_samples; 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci This->stride = nine_format_get_stride(This->base.info.format, 859bf215546Sopenharmony_ci This->desc.Width); 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci pipe_surface_reference(&This->surface[0], NULL); 862bf215546Sopenharmony_ci pipe_surface_reference(&This->surface[1], NULL); 863bf215546Sopenharmony_ci NineSurface9_CreatePipeSurfaces(This); 864bf215546Sopenharmony_ci} 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci 867bf215546Sopenharmony_cistatic const GUID *NineSurface9_IIDs[] = { 868bf215546Sopenharmony_ci &IID_IDirect3DSurface9, 869bf215546Sopenharmony_ci &IID_IDirect3DResource9, 870bf215546Sopenharmony_ci &IID_IUnknown, 871bf215546Sopenharmony_ci NULL 872bf215546Sopenharmony_ci}; 873bf215546Sopenharmony_ci 874bf215546Sopenharmony_ciHRESULT 875bf215546Sopenharmony_ciNineSurface9_new( struct NineDevice9 *pDevice, 876bf215546Sopenharmony_ci struct NineUnknown *pContainer, 877bf215546Sopenharmony_ci struct pipe_resource *pResource, 878bf215546Sopenharmony_ci struct nine_allocation *user_buffer, 879bf215546Sopenharmony_ci uint8_t TextureType, 880bf215546Sopenharmony_ci unsigned Level, 881bf215546Sopenharmony_ci unsigned Layer, 882bf215546Sopenharmony_ci D3DSURFACE_DESC *pDesc, 883bf215546Sopenharmony_ci struct NineSurface9 **ppOut ) 884bf215546Sopenharmony_ci{ 885bf215546Sopenharmony_ci NINE_DEVICE_CHILD_NEW(Surface9, ppOut, pDevice, /* args */ 886bf215546Sopenharmony_ci pContainer, pResource, user_buffer, 887bf215546Sopenharmony_ci TextureType, Level, Layer, pDesc); 888bf215546Sopenharmony_ci} 889