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