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