Home | History | Annotate | Download | only in nine
      1 /*
      2  * Copyright 2011 Joakim Sindholt <opensource (at) zhasha.com>
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
     18  * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     21  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
     22 
     23 #include "device9.h"
     24 #include "stateblock9.h"
     25 #include "surface9.h"
     26 #include "swapchain9.h"
     27 #include "swapchain9ex.h"
     28 #include "indexbuffer9.h"
     29 #include "vertexbuffer9.h"
     30 #include "vertexdeclaration9.h"
     31 #include "vertexshader9.h"
     32 #include "pixelshader9.h"
     33 #include "query9.h"
     34 #include "texture9.h"
     35 #include "cubetexture9.h"
     36 #include "volumetexture9.h"
     37 #include "nine_buffer_upload.h"
     38 #include "nine_helpers.h"
     39 #include "nine_pipe.h"
     40 #include "nine_ff.h"
     41 #include "nine_dump.h"
     42 #include "nine_limits.h"
     43 
     44 #include "pipe/p_screen.h"
     45 #include "pipe/p_context.h"
     46 #include "pipe/p_config.h"
     47 #include "util/u_math.h"
     48 #include "util/u_inlines.h"
     49 #include "util/u_hash_table.h"
     50 #include "util/u_format.h"
     51 #include "util/u_surface.h"
     52 #include "util/u_upload_mgr.h"
     53 #include "hud/hud_context.h"
     54 
     55 #include "cso_cache/cso_context.h"
     56 
     57 #define DBG_CHANNEL DBG_DEVICE
     58 
     59 #if defined(PIPE_CC_GCC) && (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64))
     60 
     61 static void nine_setup_fpu()
     62 {
     63     uint16_t c;
     64 
     65     __asm__ __volatile__ ("fnstcw %0" : "=m" (*&c));
     66 
     67     /* clear the control word */
     68     c &= 0xF0C0;
     69     /* d3d9 doc/wine tests: mask all exceptions, use single-precision
     70      * and round to nearest */
     71     c |= 0x003F;
     72 
     73     __asm__ __volatile__ ("fldcw %0" : : "m" (*&c));
     74 }
     75 
     76 #else
     77 
     78 static void nine_setup_fpu(void)
     79 {
     80     WARN_ONCE("FPU setup not supported on non-x86 platforms\n");
     81 }
     82 
     83 #endif
     84 
     85 void
     86 NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
     87 {
     88     struct NineSurface9 *refSurf = NULL;
     89 
     90     DBG("This=%p is_reset=%d\n", This, (int) is_reset);
     91 
     92     assert(!This->is_recording);
     93 
     94     nine_state_set_defaults(This, &This->caps, is_reset);
     95 
     96     refSurf = This->swapchains[0]->buffers[0];
     97     assert(refSurf);
     98 
     99     This->state.viewport.X = 0;
    100     This->state.viewport.Y = 0;
    101     This->state.viewport.Width = refSurf->desc.Width;
    102     This->state.viewport.Height = refSurf->desc.Height;
    103 
    104     nine_context_set_viewport(This, &This->state.viewport);
    105 
    106     This->state.scissor.minx = 0;
    107     This->state.scissor.miny = 0;
    108     This->state.scissor.maxx = refSurf->desc.Width;
    109     This->state.scissor.maxy = refSurf->desc.Height;
    110 
    111     nine_context_set_scissor(This, &This->state.scissor);
    112 
    113     if (This->nswapchains && This->swapchains[0]->params.EnableAutoDepthStencil) {
    114         nine_context_set_render_state(This, D3DRS_ZENABLE, TRUE);
    115         This->state.rs_advertised[D3DRS_ZENABLE] = TRUE;
    116     }
    117     if (This->state.rs_advertised[D3DRS_ZENABLE])
    118         NineDevice9_SetDepthStencilSurface(
    119             This, (IDirect3DSurface9 *)This->swapchains[0]->zsbuf);
    120 }
    121 
    122 #define GET_PCAP(n) pScreen->get_param(pScreen, PIPE_CAP_##n)
    123 HRESULT
    124 NineDevice9_ctor( struct NineDevice9 *This,
    125                   struct NineUnknownParams *pParams,
    126                   struct pipe_screen *pScreen,
    127                   D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
    128                   D3DCAPS9 *pCaps,
    129                   D3DPRESENT_PARAMETERS *pPresentationParameters,
    130                   IDirect3D9 *pD3D9,
    131                   ID3DPresentGroup *pPresentationGroup,
    132                   struct d3dadapter9_context *pCTX,
    133                   boolean ex,
    134                   D3DDISPLAYMODEEX *pFullscreenDisplayMode,
    135                   int minorVersionNum )
    136 {
    137     unsigned i;
    138     HRESULT hr = NineUnknown_ctor(&This->base, pParams);
    139 
    140     DBG("This=%p pParams=%p pScreen=%p pCreationParameters=%p pCaps=%p pPresentationParameters=%p "
    141         "pD3D9=%p pPresentationGroup=%p pCTX=%p ex=%d pFullscreenDisplayMode=%p\n",
    142         This, pParams, pScreen, pCreationParameters, pCaps, pPresentationParameters, pD3D9,
    143         pPresentationGroup, pCTX, (int) ex, pFullscreenDisplayMode);
    144 
    145     if (FAILED(hr)) { return hr; }
    146 
    147     list_inithead(&This->update_buffers);
    148     list_inithead(&This->update_textures);
    149     list_inithead(&This->managed_buffers);
    150     list_inithead(&This->managed_textures);
    151 
    152     This->screen = pScreen;
    153     This->screen_sw = pCTX->ref;
    154     This->caps = *pCaps;
    155     This->d3d9 = pD3D9;
    156     This->params = *pCreationParameters;
    157     This->ex = ex;
    158     This->present = pPresentationGroup;
    159     This->minor_version_num = minorVersionNum;
    160 
    161     IDirect3D9_AddRef(This->d3d9);
    162     ID3DPresentGroup_AddRef(This->present);
    163 
    164     if (!(This->params.BehaviorFlags & D3DCREATE_FPU_PRESERVE))
    165         nine_setup_fpu();
    166 
    167     if (This->params.BehaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING) {
    168         DBG("Application asked full Software Vertex Processing.\n");
    169         This->swvp = true;
    170         This->may_swvp = true;
    171     } else
    172         This->swvp = false;
    173     if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) {
    174         DBG("Application asked mixed Software Vertex Processing.\n");
    175         This->may_swvp = true;
    176     }
    177     This->context.swvp = This->swvp;
    178     /* TODO: check if swvp is resetted by device Resets */
    179 
    180     if (This->may_swvp &&
    181         (This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX,
    182                                         PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE)
    183                                      < (NINE_MAX_CONST_F_SWVP/2) * sizeof(float[4]) ||
    184          This->screen->get_shader_param(This->screen, PIPE_SHADER_VERTEX,
    185                                         PIPE_SHADER_CAP_MAX_CONST_BUFFERS) < 5)) {
    186         /* Note: We just go on, some apps never use the abilities of
    187          * swvp, and just set more constants than allowed at init.
    188          * Only cards we support that are affected are the r500 */
    189         WARN("Card unable to handle Software Vertex Processing. Game may fail\n");
    190     }
    191 
    192     /* When may_swvp, SetConstant* limits are different */
    193     if (This->may_swvp)
    194         This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP;
    195 
    196     This->context.pipe = This->screen->context_create(This->screen, NULL, 0);
    197     This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0);
    198     if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */
    199     This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0);
    200     if (!This->pipe_sw) { return E_OUTOFMEMORY; }
    201 
    202     This->context.cso = cso_create_context(This->context.pipe);
    203     if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */
    204     This->cso_sw = cso_create_context(This->pipe_sw);
    205     if (!This->cso_sw) { return E_OUTOFMEMORY; }
    206 
    207     /* Create first, it messes up our state. */
    208     This->hud = hud_create(This->context.pipe, This->context.cso); /* NULL result is fine */
    209 
    210     /* Available memory counter. Updated only for allocations with this device
    211      * instance. This is the Win 7 behavior.
    212      * Win XP shares this counter across multiple devices. */
    213     This->available_texture_mem = This->screen->get_param(This->screen, PIPE_CAP_VIDEO_MEMORY);
    214     if (This->available_texture_mem < 4096)
    215         This->available_texture_mem <<= 20;
    216     else
    217         This->available_texture_mem = UINT_MAX;
    218     /* We cap texture memory usage to 80% of what is reported free initially
    219      * This helps get closer Win behaviour. For example VertexBuffer allocation
    220      * still succeeds when texture allocation fails. */
    221     This->available_texture_limit = This->available_texture_mem * 20LL / 100LL;
    222 
    223     /* create implicit swapchains */
    224     This->nswapchains = ID3DPresentGroup_GetMultiheadCount(This->present);
    225     This->swapchains = CALLOC(This->nswapchains,
    226                               sizeof(struct NineSwapChain9 *));
    227     if (!This->swapchains) { return E_OUTOFMEMORY; }
    228 
    229     for (i = 0; i < This->nswapchains; ++i) {
    230         ID3DPresent *present;
    231 
    232         hr = ID3DPresentGroup_GetPresent(This->present, i, &present);
    233         if (FAILED(hr))
    234             return hr;
    235 
    236         if (ex) {
    237             D3DDISPLAYMODEEX *mode = NULL;
    238             struct NineSwapChain9Ex **ret =
    239                 (struct NineSwapChain9Ex **)&This->swapchains[i];
    240 
    241             if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
    242             /* when this is a Device9Ex, it should create SwapChain9Exs */
    243             hr = NineSwapChain9Ex_new(This, TRUE, present,
    244                                       &pPresentationParameters[i], pCTX,
    245                                       This->params.hFocusWindow, mode, ret);
    246         } else {
    247             hr = NineSwapChain9_new(This, TRUE, present,
    248                                     &pPresentationParameters[i], pCTX,
    249                                     This->params.hFocusWindow,
    250                                     &This->swapchains[i]);
    251         }
    252 
    253         ID3DPresent_Release(present);
    254         if (FAILED(hr))
    255             return hr;
    256         NineUnknown_ConvertRefToBind(NineUnknown(This->swapchains[i]));
    257 
    258         hr = NineSwapChain9_GetBackBuffer(This->swapchains[i], 0,
    259                                           D3DBACKBUFFER_TYPE_MONO,
    260                                           (IDirect3DSurface9 **)
    261                                           &This->state.rt[i]);
    262         if (FAILED(hr))
    263             return hr;
    264         NineUnknown_ConvertRefToBind(NineUnknown(This->state.rt[i]));
    265         nine_bind(&This->context.rt[i], This->state.rt[i]);
    266     }
    267 
    268     /* Initialize CSMT */
    269     if (pCTX->csmt_force == 1)
    270         This->csmt_active = true;
    271     else if (pCTX->csmt_force == 0)
    272         This->csmt_active = false;
    273     else
    274         /* r600 and radeonsi are thread safe. */
    275         This->csmt_active = strstr(pScreen->get_name(pScreen), "AMD") != NULL;
    276 
    277     /* We rely on u_upload_mgr using persistent coherent buffers (which don't
    278      * require flush to work in multi-pipe_context scenario) for vertex and
    279      * index buffers */
    280     if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT))
    281         This->csmt_active = false;
    282 
    283     if (This->csmt_active) {
    284         This->csmt_ctx = nine_csmt_create(This);
    285         if (!This->csmt_ctx)
    286             return E_OUTOFMEMORY;
    287     }
    288 
    289     if (This->csmt_active)
    290         DBG("\033[1;32mCSMT is active\033[0m\n");
    291 
    292     This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4);
    293 
    294     /* Initialize a dummy VBO to be used when a vertex declaration does not
    295      * specify all the inputs needed by vertex shader, on win default behavior
    296      * is to pass 0,0,0,0 to the shader */
    297     {
    298         struct pipe_transfer *transfer;
    299         struct pipe_resource tmpl;
    300         struct pipe_box box;
    301         unsigned char *data;
    302 
    303         memset(&tmpl, 0, sizeof(tmpl));
    304         tmpl.target = PIPE_BUFFER;
    305         tmpl.format = PIPE_FORMAT_R8_UNORM;
    306         tmpl.width0 = 16; /* 4 floats */
    307         tmpl.height0 = 1;
    308         tmpl.depth0 = 1;
    309         tmpl.array_size = 1;
    310         tmpl.last_level = 0;
    311         tmpl.nr_samples = 0;
    312         tmpl.usage = PIPE_USAGE_DEFAULT;
    313         tmpl.bind = PIPE_BIND_VERTEX_BUFFER;
    314         tmpl.flags = 0;
    315         This->dummy_vbo = pScreen->resource_create(pScreen, &tmpl);
    316 
    317         if (!This->dummy_vbo)
    318             return D3DERR_OUTOFVIDEOMEMORY;
    319 
    320         u_box_1d(0, 16, &box);
    321         data = This->context.pipe->transfer_map(This->context.pipe, This->dummy_vbo, 0,
    322                                         PIPE_TRANSFER_WRITE |
    323                                         PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
    324                                         &box, &transfer);
    325         assert(data);
    326         assert(transfer);
    327         memset(data, 0, 16);
    328         This->context.pipe->transfer_unmap(This->context.pipe, transfer);
    329     }
    330 
    331     This->cursor.software = FALSE;
    332     This->cursor.hotspot.x = -1;
    333     This->cursor.hotspot.y = -1;
    334     {
    335         struct pipe_resource tmpl;
    336         memset(&tmpl, 0, sizeof(tmpl));
    337         tmpl.target = PIPE_TEXTURE_2D;
    338         tmpl.format = PIPE_FORMAT_R8G8B8A8_UNORM;
    339         tmpl.width0 = 64;
    340         tmpl.height0 = 64;
    341         tmpl.depth0 = 1;
    342         tmpl.array_size = 1;
    343         tmpl.last_level = 0;
    344         tmpl.nr_samples = 0;
    345         tmpl.usage = PIPE_USAGE_DEFAULT;
    346         tmpl.bind = PIPE_BIND_CURSOR | PIPE_BIND_SAMPLER_VIEW;
    347         tmpl.flags = 0;
    348 
    349         This->cursor.image = pScreen->resource_create(pScreen, &tmpl);
    350         if (!This->cursor.image)
    351             return D3DERR_OUTOFVIDEOMEMORY;
    352 
    353         /* For uploading 32x32 (argb) cursor */
    354         This->cursor.hw_upload_temp = MALLOC(32 * 4 * 32);
    355         if (!This->cursor.hw_upload_temp)
    356             return D3DERR_OUTOFVIDEOMEMORY;
    357     }
    358 
    359     /* Create constant buffers. */
    360     {
    361         unsigned max_const_vs, max_const_ps;
    362 
    363         /* vs 3.0: >= 256 float constants, but for cards with exactly 256 slots,
    364          * we have to take in some more slots for int and bool*/
    365         max_const_vs = _min(pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX,
    366                                 PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE) /
    367                                 sizeof(float[4]),
    368                             NINE_MAX_CONST_ALL);
    369         /* ps 3.0: 224 float constants. All cards supported support at least
    370          * 256 constants for ps */
    371         max_const_ps = NINE_MAX_CONST_F_PS3 + (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
    372 
    373         This->max_vs_const_f = max_const_vs -
    374                                (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
    375         This->max_ps_const_f = max_const_ps -
    376                                (NINE_MAX_CONST_I + NINE_MAX_CONST_B / 4);
    377 
    378         This->vs_const_size = max_const_vs * sizeof(float[4]);
    379         This->ps_const_size = max_const_ps * sizeof(float[4]);
    380         /* Include space for I,B constants for user constbuf. */
    381         if (This->may_swvp) {
    382             This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);
    383             This->context.vs_const_f_swvp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);
    384             if (!This->context.vs_const_f_swvp)
    385                 return E_OUTOFMEMORY;
    386             This->state.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);
    387             This->context.vs_lconstf_temp = CALLOC(NINE_MAX_CONST_F_SWVP * sizeof(float[4]),1);
    388             This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1);
    389             This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I_SWVP * sizeof(int[4]), 1);
    390             This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1);
    391             This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B_SWVP * sizeof(BOOL), 1);
    392         } else {
    393             This->state.vs_const_f = CALLOC(NINE_MAX_CONST_F * sizeof(float[4]), 1);
    394             This->context.vs_const_f_swvp = NULL;
    395             This->state.vs_lconstf_temp = CALLOC(This->vs_const_size,1);
    396             This->context.vs_lconstf_temp = CALLOC(This->vs_const_size,1);
    397             This->state.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1);
    398             This->context.vs_const_i = CALLOC(NINE_MAX_CONST_I * sizeof(int[4]), 1);
    399             This->state.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1);
    400             This->context.vs_const_b = CALLOC(NINE_MAX_CONST_B * sizeof(BOOL), 1);
    401         }
    402         This->context.vs_const_f = CALLOC(This->vs_const_size, 1);
    403         This->state.ps_const_f = CALLOC(This->ps_const_size, 1);
    404         This->context.ps_const_f = CALLOC(This->ps_const_size, 1);
    405         This->context.ps_lconstf_temp = CALLOC(This->ps_const_size,1);
    406         if (!This->state.vs_const_f || !This->context.vs_const_f ||
    407             !This->state.ps_const_f || !This->context.ps_const_f ||
    408             !This->state.vs_lconstf_temp || !This->context.vs_lconstf_temp ||
    409             !This->context.ps_lconstf_temp ||
    410             !This->state.vs_const_i || !This->context.vs_const_i ||
    411             !This->state.vs_const_b || !This->context.vs_const_b)
    412             return E_OUTOFMEMORY;
    413 
    414         if (strstr(pScreen->get_name(pScreen), "AMD") ||
    415             strstr(pScreen->get_name(pScreen), "ATI")) {
    416             This->driver_bugs.buggy_barycentrics = TRUE;
    417         }
    418     }
    419 
    420     /* allocate dummy texture/sampler for when there are missing ones bound */
    421     {
    422         struct pipe_resource tmplt;
    423         struct pipe_sampler_view templ;
    424         struct pipe_sampler_state samp;
    425         memset(&tmplt, 0, sizeof(tmplt));
    426         memset(&samp, 0, sizeof(samp));
    427 
    428         tmplt.target = PIPE_TEXTURE_2D;
    429         tmplt.width0 = 1;
    430         tmplt.height0 = 1;
    431         tmplt.depth0 = 1;
    432         tmplt.last_level = 0;
    433         tmplt.array_size = 1;
    434         tmplt.usage = PIPE_USAGE_DEFAULT;
    435         tmplt.flags = 0;
    436         tmplt.format = PIPE_FORMAT_B8G8R8A8_UNORM;
    437         tmplt.bind = PIPE_BIND_SAMPLER_VIEW;
    438         tmplt.nr_samples = 0;
    439 
    440         This->dummy_texture = This->screen->resource_create(This->screen, &tmplt);
    441         if (!This->dummy_texture)
    442             return D3DERR_DRIVERINTERNALERROR;
    443 
    444         templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
    445         templ.u.tex.first_layer = 0;
    446         templ.u.tex.last_layer = 0;
    447         templ.u.tex.first_level = 0;
    448         templ.u.tex.last_level = 0;
    449         templ.swizzle_r = PIPE_SWIZZLE_0;
    450         templ.swizzle_g = PIPE_SWIZZLE_0;
    451         templ.swizzle_b = PIPE_SWIZZLE_0;
    452         templ.swizzle_a = PIPE_SWIZZLE_1;
    453         templ.target = This->dummy_texture->target;
    454 
    455         This->dummy_sampler_view = This->context.pipe->create_sampler_view(This->context.pipe, This->dummy_texture, &templ);
    456         if (!This->dummy_sampler_view)
    457             return D3DERR_DRIVERINTERNALERROR;
    458 
    459         samp.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    460         samp.max_lod = 15.0f;
    461         samp.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    462         samp.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    463         samp.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    464         samp.min_img_filter = PIPE_TEX_FILTER_NEAREST;
    465         samp.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
    466         samp.compare_mode = PIPE_TEX_COMPARE_NONE;
    467         samp.compare_func = PIPE_FUNC_LEQUAL;
    468         samp.normalized_coords = 1;
    469         samp.seamless_cube_map = 0;
    470         This->dummy_sampler_state = samp;
    471     }
    472 
    473     /* Allocate upload helper for drivers that suck (from st pov ;). */
    474 
    475     This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS) && !This->csmt_active;
    476     This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS) && !This->csmt_active;
    477     This->driver_caps.user_cbufs = GET_PCAP(USER_CONSTANT_BUFFERS);
    478     This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS);
    479     This->driver_caps.user_sw_cbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_CONSTANT_BUFFERS);
    480 
    481     /* Implicit use of context pipe for vertex and index uploaded when
    482      * csmt is not active. Does not need to sync since csmt is unactive,
    483      * thus no need to call NineDevice9_GetPipe at each upload. */
    484     if (!This->driver_caps.user_vbufs)
    485         This->vertex_uploader = u_upload_create(This->csmt_active ?
    486                                                     This->pipe_secondary : This->context.pipe,
    487                                                 65536,
    488                                                 PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM);
    489     This->vertex_sw_uploader = u_upload_create(This->pipe_sw, 65536,
    490                                             PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM);
    491     if (!This->driver_caps.user_ibufs)
    492         This->index_uploader = u_upload_create(This->csmt_active ?
    493                                                     This->pipe_secondary : This->context.pipe,
    494                                                128 * 1024,
    495                                                PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM);
    496     if (!This->driver_caps.user_cbufs) {
    497         This->constbuf_alignment = GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT);
    498         This->constbuf_uploader = u_upload_create(This->context.pipe, This->vs_const_size,
    499                                                   PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM);
    500     }
    501 
    502     This->constbuf_sw_uploader = u_upload_create(This->pipe_sw, 128 * 1024,
    503                                                  PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM);
    504 
    505     This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
    506     This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS);
    507     This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS);
    508     This->driver_caps.offset_units_unscaled = GET_PCAP(POLYGON_OFFSET_UNITS_UNSCALED);
    509 
    510     nine_ff_init(This); /* initialize fixed function code */
    511 
    512     NineDevice9_SetDefaultState(This, FALSE);
    513 
    514     {
    515         struct pipe_poly_stipple stipple;
    516         memset(&stipple, ~0, sizeof(stipple));
    517         This->context.pipe->set_polygon_stipple(This->context.pipe, &stipple);
    518     }
    519 
    520     This->update = &This->state;
    521 
    522     nine_state_init_sw(This);
    523 
    524     ID3DPresentGroup_Release(This->present);
    525     nine_csmt_process(This);
    526 
    527     return D3D_OK;
    528 }
    529 #undef GET_PCAP
    530 
    531 void
    532 NineDevice9_dtor( struct NineDevice9 *This )
    533 {
    534     unsigned i;
    535 
    536     DBG("This=%p\n", This);
    537 
    538     /* Flush all pending commands to get refcount right,
    539      * and properly release bound objects. It is ok to still
    540      * execute commands while we are in device dtor, because
    541      * we haven't released anything yet. Note that no pending
    542      * command can increase the device refcount. */
    543     if (This->csmt_active && This->csmt_ctx) {
    544         nine_csmt_process(This);
    545         nine_csmt_destroy(This, This->csmt_ctx);
    546         This->csmt_active = FALSE;
    547         This->csmt_ctx = NULL;
    548     }
    549 
    550     nine_ff_fini(This);
    551     nine_state_destroy_sw(This);
    552     nine_state_clear(&This->state, TRUE);
    553     nine_context_clear(This);
    554 
    555     if (This->vertex_uploader)
    556         u_upload_destroy(This->vertex_uploader);
    557     if (This->index_uploader)
    558         u_upload_destroy(This->index_uploader);
    559     if (This->constbuf_uploader)
    560         u_upload_destroy(This->constbuf_uploader);
    561     if (This->vertex_sw_uploader)
    562         u_upload_destroy(This->vertex_sw_uploader);
    563     if (This->constbuf_sw_uploader)
    564         u_upload_destroy(This->constbuf_sw_uploader);
    565 
    566     nine_bind(&This->record, NULL);
    567 
    568     pipe_sampler_view_reference(&This->dummy_sampler_view, NULL);
    569     pipe_resource_reference(&This->dummy_texture, NULL);
    570     pipe_resource_reference(&This->dummy_vbo, NULL);
    571     FREE(This->state.vs_const_f);
    572     FREE(This->context.vs_const_f);
    573     FREE(This->state.ps_const_f);
    574     FREE(This->context.ps_const_f);
    575     FREE(This->state.vs_lconstf_temp);
    576     FREE(This->context.vs_lconstf_temp);
    577     FREE(This->context.ps_lconstf_temp);
    578     FREE(This->state.vs_const_i);
    579     FREE(This->context.vs_const_i);
    580     FREE(This->state.vs_const_b);
    581     FREE(This->context.vs_const_b);
    582     FREE(This->context.vs_const_f_swvp);
    583 
    584     pipe_resource_reference(&This->cursor.image, NULL);
    585     FREE(This->cursor.hw_upload_temp);
    586 
    587     if (This->swapchains) {
    588         for (i = 0; i < This->nswapchains; ++i)
    589             if (This->swapchains[i])
    590                 NineUnknown_Unbind(NineUnknown(This->swapchains[i]));
    591         FREE(This->swapchains);
    592     }
    593 
    594     if (This->buffer_upload)
    595         nine_upload_destroy(This->buffer_upload);
    596 
    597     /* Destroy cso first */
    598     if (This->context.cso) { cso_destroy_context(This->context.cso); }
    599     if (This->cso_sw) { cso_destroy_context(This->cso_sw); }
    600     if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); }
    601     if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); }
    602     if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); }
    603 
    604     if (This->present) { ID3DPresentGroup_Release(This->present); }
    605     if (This->d3d9) { IDirect3D9_Release(This->d3d9); }
    606 
    607     NineUnknown_dtor(&This->base);
    608 }
    609 
    610 struct pipe_screen *
    611 NineDevice9_GetScreen( struct NineDevice9 *This )
    612 {
    613     return This->screen;
    614 }
    615 
    616 struct pipe_context *
    617 NineDevice9_GetPipe( struct NineDevice9 *This )
    618 {
    619     return nine_context_get_pipe(This);
    620 }
    621 
    622 const D3DCAPS9 *
    623 NineDevice9_GetCaps( struct NineDevice9 *This )
    624 {
    625     return &This->caps;
    626 }
    627 
    628 static inline void
    629 NineDevice9_PauseRecording( struct NineDevice9 *This )
    630 {
    631     if (This->record) {
    632         This->update = &This->state;
    633         This->is_recording = FALSE;
    634     }
    635 }
    636 
    637 static inline void
    638 NineDevice9_ResumeRecording( struct NineDevice9 *This )
    639 {
    640     if (This->record) {
    641         This->update = &This->record->state;
    642         This->is_recording = TRUE;
    643     }
    644 }
    645 
    646 HRESULT NINE_WINAPI
    647 NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )
    648 {
    649     if (NineSwapChain9_GetOccluded(This->swapchains[0])) {
    650         This->device_needs_reset = TRUE;
    651         return D3DERR_DEVICELOST;
    652     } else if (NineSwapChain9_ResolutionMismatch(This->swapchains[0])) {
    653         This->device_needs_reset = TRUE;
    654         return D3DERR_DEVICENOTRESET;
    655     } else if (This->device_needs_reset) {
    656         return D3DERR_DEVICENOTRESET;
    657     }
    658 
    659     return D3D_OK;
    660 }
    661 
    662 UINT NINE_WINAPI
    663 NineDevice9_GetAvailableTextureMem( struct NineDevice9 *This )
    664 {
    665     return This->available_texture_mem;
    666 }
    667 
    668 HRESULT NINE_WINAPI
    669 NineDevice9_EvictManagedResources( struct NineDevice9 *This )
    670 {
    671     struct NineBaseTexture9 *tex;
    672     struct NineBuffer9 *buf;
    673 
    674     DBG("This=%p\n", This);
    675     LIST_FOR_EACH_ENTRY(tex, &This->managed_textures, list2) {
    676         NineBaseTexture9_UnLoad(tex);
    677     }
    678     /* Vertex/index buffers don't take a lot of space and aren't accounted
    679      * for d3d memory usage. Instead of actually freeing from memory,
    680      * just mark the buffer dirty to trigger a re-upload later. We
    681      * could just ignore, but some bad behaving apps could rely on it (if
    682      * they write outside the locked regions typically). */
    683     LIST_FOR_EACH_ENTRY(buf, &This->managed_buffers, managed.list2) {
    684         NineBuffer9_SetDirty(buf);
    685     }
    686 
    687     return D3D_OK;
    688 }
    689 
    690 HRESULT NINE_WINAPI
    691 NineDevice9_GetDirect3D( struct NineDevice9 *This,
    692                          IDirect3D9 **ppD3D9 )
    693 {
    694     user_assert(ppD3D9 != NULL, E_POINTER);
    695     IDirect3D9_AddRef(This->d3d9);
    696     *ppD3D9 = This->d3d9;
    697     return D3D_OK;
    698 }
    699 
    700 HRESULT NINE_WINAPI
    701 NineDevice9_GetDeviceCaps( struct NineDevice9 *This,
    702                            D3DCAPS9 *pCaps )
    703 {
    704     user_assert(pCaps != NULL, D3DERR_INVALIDCALL);
    705     *pCaps = This->caps;
    706     return D3D_OK;
    707 }
    708 
    709 HRESULT NINE_WINAPI
    710 NineDevice9_GetDisplayMode( struct NineDevice9 *This,
    711                             UINT iSwapChain,
    712                             D3DDISPLAYMODE *pMode )
    713 {
    714     DBG("This=%p iSwapChain=%u pMode=%p\n", This, iSwapChain, pMode);
    715 
    716     user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
    717 
    718     return NineSwapChain9_GetDisplayMode(This->swapchains[iSwapChain], pMode);
    719 }
    720 
    721 HRESULT NINE_WINAPI
    722 NineDevice9_GetCreationParameters( struct NineDevice9 *This,
    723                                    D3DDEVICE_CREATION_PARAMETERS *pParameters )
    724 {
    725     user_assert(pParameters != NULL, D3DERR_INVALIDCALL);
    726     *pParameters = This->params;
    727     return D3D_OK;
    728 }
    729 
    730 HRESULT NINE_WINAPI
    731 NineDevice9_SetCursorProperties( struct NineDevice9 *This,
    732                                  UINT XHotSpot,
    733                                  UINT YHotSpot,
    734                                  IDirect3DSurface9 *pCursorBitmap )
    735 {
    736     struct NineSurface9 *surf = NineSurface9(pCursorBitmap);
    737     struct pipe_context *pipe = NineDevice9_GetPipe(This);
    738     struct pipe_box box;
    739     struct pipe_transfer *transfer;
    740     BOOL hw_cursor;
    741     void *ptr;
    742 
    743     DBG_FLAG(DBG_SWAPCHAIN, "This=%p XHotSpot=%u YHotSpot=%u "
    744              "pCursorBitmap=%p\n", This, XHotSpot, YHotSpot, pCursorBitmap);
    745 
    746     user_assert(pCursorBitmap, D3DERR_INVALIDCALL);
    747     user_assert(surf->desc.Format == D3DFMT_A8R8G8B8, D3DERR_INVALIDCALL);
    748 
    749     if (This->swapchains[0]->params.Windowed) {
    750         This->cursor.w = MIN2(surf->desc.Width, 32);
    751         This->cursor.h = MIN2(surf->desc.Height, 32);
    752         hw_cursor = 1; /* always use hw cursor for windowed mode */
    753     } else {
    754         This->cursor.w = MIN2(surf->desc.Width, This->cursor.image->width0);
    755         This->cursor.h = MIN2(surf->desc.Height, This->cursor.image->height0);
    756         hw_cursor = This->cursor.w == 32 && This->cursor.h == 32;
    757     }
    758 
    759     u_box_origin_2d(This->cursor.w, This->cursor.h, &box);
    760 
    761     ptr = pipe->transfer_map(pipe, This->cursor.image, 0,
    762                              PIPE_TRANSFER_WRITE |
    763                              PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE,
    764                              &box, &transfer);
    765     if (!ptr)
    766         ret_err("Failed to update cursor image.\n", D3DERR_DRIVERINTERNALERROR);
    767 
    768     This->cursor.hotspot.x = XHotSpot;
    769     This->cursor.hotspot.y = YHotSpot;
    770 
    771     /* Copy cursor image to internal storage. */
    772     {
    773         D3DLOCKED_RECT lock;
    774         HRESULT hr;
    775         const struct util_format_description *sfmt =
    776             util_format_description(surf->base.info.format);
    777         assert(sfmt);
    778 
    779         hr = NineSurface9_LockRect(surf, &lock, NULL, D3DLOCK_READONLY);
    780         if (FAILED(hr))
    781             ret_err("Failed to map cursor source image.\n",
    782                     D3DERR_DRIVERINTERNALERROR);
    783 
    784         sfmt->unpack_rgba_8unorm(ptr, transfer->stride,
    785                                  lock.pBits, lock.Pitch,
    786                                  This->cursor.w, This->cursor.h);
    787 
    788         if (hw_cursor) {
    789             void *data = lock.pBits;
    790             /* SetCursor assumes 32x32 argb with pitch 128 */
    791             if (lock.Pitch != 128) {
    792                 sfmt->unpack_rgba_8unorm(This->cursor.hw_upload_temp, 128,
    793                                          lock.pBits, lock.Pitch,
    794                                          32, 32);
    795                 data = This->cursor.hw_upload_temp;
    796             }
    797             hw_cursor = ID3DPresent_SetCursor(This->swapchains[0]->present,
    798                                               data,
    799                                               &This->cursor.hotspot,
    800                                               This->cursor.visible) == D3D_OK;
    801         }
    802 
    803         NineSurface9_UnlockRect(surf);
    804     }
    805     pipe->transfer_unmap(pipe, transfer);
    806 
    807     /* hide cursor if we emulate it */
    808     if (!hw_cursor)
    809         ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, FALSE);
    810     This->cursor.software = !hw_cursor;
    811 
    812     return D3D_OK;
    813 }
    814 
    815 void NINE_WINAPI
    816 NineDevice9_SetCursorPosition( struct NineDevice9 *This,
    817                                int X,
    818                                int Y,
    819                                DWORD Flags )
    820 {
    821     struct NineSwapChain9 *swap = This->swapchains[0];
    822 
    823     DBG("This=%p X=%d Y=%d Flags=%d\n", This, X, Y, Flags);
    824 
    825     This->cursor.pos.x = X;
    826     This->cursor.pos.y = Y;
    827 
    828     if (!This->cursor.software)
    829         This->cursor.software = ID3DPresent_SetCursorPos(swap->present, &This->cursor.pos) != D3D_OK;
    830 }
    831 
    832 BOOL NINE_WINAPI
    833 NineDevice9_ShowCursor( struct NineDevice9 *This,
    834                         BOOL bShow )
    835 {
    836     BOOL old = This->cursor.visible;
    837 
    838     DBG("This=%p bShow=%d\n", This, (int) bShow);
    839 
    840     This->cursor.visible = bShow && (This->cursor.hotspot.x != -1);
    841     if (!This->cursor.software)
    842         This->cursor.software = ID3DPresent_SetCursor(This->swapchains[0]->present, NULL, NULL, bShow) != D3D_OK;
    843 
    844     return old;
    845 }
    846 
    847 HRESULT NINE_WINAPI
    848 NineDevice9_CreateAdditionalSwapChain( struct NineDevice9 *This,
    849                                        D3DPRESENT_PARAMETERS *pPresentationParameters,
    850                                        IDirect3DSwapChain9 **pSwapChain )
    851 {
    852     struct NineSwapChain9 *swapchain, *tmplt = This->swapchains[0];
    853     ID3DPresent *present;
    854     HRESULT hr;
    855 
    856     DBG("This=%p pPresentationParameters=%p pSwapChain=%p\n",
    857         This, pPresentationParameters, pSwapChain);
    858 
    859     user_assert(pPresentationParameters, D3DERR_INVALIDCALL);
    860     user_assert(tmplt->params.Windowed && pPresentationParameters->Windowed, D3DERR_INVALIDCALL);
    861 
    862     /* TODO: this deserves more tests */
    863     if (!pPresentationParameters->hDeviceWindow)
    864         pPresentationParameters->hDeviceWindow = This->params.hFocusWindow;
    865 
    866     hr = ID3DPresentGroup_CreateAdditionalPresent(This->present, pPresentationParameters, &present);
    867 
    868     if (FAILED(hr))
    869         return hr;
    870 
    871     hr = NineSwapChain9_new(This, FALSE, present, pPresentationParameters,
    872                             tmplt->actx,
    873                             tmplt->params.hDeviceWindow,
    874                             &swapchain);
    875     if (FAILED(hr))
    876         return hr;
    877 
    878     *pSwapChain = (IDirect3DSwapChain9 *)swapchain;
    879     return D3D_OK;
    880 }
    881 
    882 HRESULT NINE_WINAPI
    883 NineDevice9_GetSwapChain( struct NineDevice9 *This,
    884                           UINT iSwapChain,
    885                           IDirect3DSwapChain9 **pSwapChain )
    886 {
    887     user_assert(pSwapChain != NULL, D3DERR_INVALIDCALL);
    888 
    889     *pSwapChain = NULL;
    890     user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
    891 
    892     NineUnknown_AddRef(NineUnknown(This->swapchains[iSwapChain]));
    893     *pSwapChain = (IDirect3DSwapChain9 *)This->swapchains[iSwapChain];
    894 
    895     return D3D_OK;
    896 }
    897 
    898 UINT NINE_WINAPI
    899 NineDevice9_GetNumberOfSwapChains( struct NineDevice9 *This )
    900 {
    901     return This->nswapchains;
    902 }
    903 
    904 HRESULT NINE_WINAPI
    905 NineDevice9_Reset( struct NineDevice9 *This,
    906                    D3DPRESENT_PARAMETERS *pPresentationParameters )
    907 {
    908     HRESULT hr = D3D_OK;
    909     unsigned i;
    910 
    911     DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
    912 
    913     if (NineSwapChain9_GetOccluded(This->swapchains[0])) {
    914         This->device_needs_reset = TRUE;
    915         return D3DERR_DEVICELOST;
    916     }
    917 
    918     for (i = 0; i < This->nswapchains; ++i) {
    919         D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
    920         hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
    921         if (hr != D3D_OK)
    922             break;
    923     }
    924 
    925     nine_csmt_process(This);
    926     nine_state_clear(&This->state, TRUE);
    927     nine_context_clear(This);
    928 
    929     NineDevice9_SetDefaultState(This, TRUE);
    930     NineDevice9_SetRenderTarget(
    931         This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);
    932     /* XXX: better use GetBackBuffer here ? */
    933 
    934     This->device_needs_reset = (hr != D3D_OK);
    935     return hr;
    936 }
    937 
    938 HRESULT NINE_WINAPI
    939 NineDevice9_Present( struct NineDevice9 *This,
    940                      const RECT *pSourceRect,
    941                      const RECT *pDestRect,
    942                      HWND hDestWindowOverride,
    943                      const RGNDATA *pDirtyRegion )
    944 {
    945     unsigned i;
    946     HRESULT hr;
    947 
    948     DBG("This=%p pSourceRect=%p pDestRect=%p hDestWindowOverride=%p pDirtyRegion=%p\n",
    949         This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
    950 
    951     /* XXX is this right? */
    952     for (i = 0; i < This->nswapchains; ++i) {
    953         hr = NineSwapChain9_Present(This->swapchains[i], pSourceRect, pDestRect,
    954                                     hDestWindowOverride, pDirtyRegion, 0);
    955         if (FAILED(hr)) { return hr; }
    956     }
    957 
    958     return D3D_OK;
    959 }
    960 
    961 HRESULT NINE_WINAPI
    962 NineDevice9_GetBackBuffer( struct NineDevice9 *This,
    963                            UINT iSwapChain,
    964                            UINT iBackBuffer,
    965                            D3DBACKBUFFER_TYPE Type,
    966                            IDirect3DSurface9 **ppBackBuffer )
    967 {
    968     user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL);
    969     /* return NULL on error */
    970     *ppBackBuffer = NULL;
    971     user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
    972 
    973     return NineSwapChain9_GetBackBuffer(This->swapchains[iSwapChain],
    974                                         iBackBuffer, Type, ppBackBuffer);
    975 }
    976 
    977 HRESULT NINE_WINAPI
    978 NineDevice9_GetRasterStatus( struct NineDevice9 *This,
    979                              UINT iSwapChain,
    980                              D3DRASTER_STATUS *pRasterStatus )
    981 {
    982     user_assert(pRasterStatus != NULL, D3DERR_INVALIDCALL);
    983     user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
    984 
    985     return NineSwapChain9_GetRasterStatus(This->swapchains[iSwapChain],
    986                                           pRasterStatus);
    987 }
    988 
    989 HRESULT NINE_WINAPI
    990 NineDevice9_SetDialogBoxMode( struct NineDevice9 *This,
    991                               BOOL bEnableDialogs )
    992 {
    993     STUB(D3DERR_INVALIDCALL);
    994 }
    995 
    996 void NINE_WINAPI
    997 NineDevice9_SetGammaRamp( struct NineDevice9 *This,
    998                           UINT iSwapChain,
    999                           DWORD Flags,
   1000                           const D3DGAMMARAMP *pRamp )
   1001 {
   1002     DBG("This=%p iSwapChain=%u Flags=%x pRamp=%p\n", This,
   1003         iSwapChain, Flags, pRamp);
   1004 
   1005     user_warn(iSwapChain >= This->nswapchains);
   1006     user_warn(!pRamp);
   1007 
   1008     if (pRamp && (iSwapChain < This->nswapchains)) {
   1009         struct NineSwapChain9 *swap = This->swapchains[iSwapChain];
   1010         swap->gamma = *pRamp;
   1011         ID3DPresent_SetGammaRamp(swap->present, pRamp, swap->params.hDeviceWindow);
   1012     }
   1013 }
   1014 
   1015 void NINE_WINAPI
   1016 NineDevice9_GetGammaRamp( struct NineDevice9 *This,
   1017                           UINT iSwapChain,
   1018                           D3DGAMMARAMP *pRamp )
   1019 {
   1020     DBG("This=%p iSwapChain=%u pRamp=%p\n", This, iSwapChain, pRamp);
   1021 
   1022     user_warn(iSwapChain >= This->nswapchains);
   1023     user_warn(!pRamp);
   1024 
   1025     if (pRamp && (iSwapChain < This->nswapchains))
   1026         *pRamp = This->swapchains[iSwapChain]->gamma;
   1027 }
   1028 
   1029 HRESULT NINE_WINAPI
   1030 NineDevice9_CreateTexture( struct NineDevice9 *This,
   1031                            UINT Width,
   1032                            UINT Height,
   1033                            UINT Levels,
   1034                            DWORD Usage,
   1035                            D3DFORMAT Format,
   1036                            D3DPOOL Pool,
   1037                            IDirect3DTexture9 **ppTexture,
   1038                            HANDLE *pSharedHandle )
   1039 {
   1040     struct NineTexture9 *tex;
   1041     HRESULT hr;
   1042 
   1043     DBG("This=%p Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s "
   1044         "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Levels,
   1045         nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
   1046         nine_D3DPOOL_to_str(Pool), ppTexture, pSharedHandle);
   1047 
   1048     Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DMAP |
   1049              D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
   1050              D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI;
   1051 
   1052     *ppTexture = NULL;
   1053 
   1054     hr = NineTexture9_new(This, Width, Height, Levels, Usage, Format, Pool,
   1055                           &tex, pSharedHandle);
   1056     if (SUCCEEDED(hr))
   1057         *ppTexture = (IDirect3DTexture9 *)tex;
   1058 
   1059     return hr;
   1060 }
   1061 
   1062 HRESULT NINE_WINAPI
   1063 NineDevice9_CreateVolumeTexture( struct NineDevice9 *This,
   1064                                  UINT Width,
   1065                                  UINT Height,
   1066                                  UINT Depth,
   1067                                  UINT Levels,
   1068                                  DWORD Usage,
   1069                                  D3DFORMAT Format,
   1070                                  D3DPOOL Pool,
   1071                                  IDirect3DVolumeTexture9 **ppVolumeTexture,
   1072                                  HANDLE *pSharedHandle )
   1073 {
   1074     struct NineVolumeTexture9 *tex;
   1075     HRESULT hr;
   1076 
   1077     DBG("This=%p Width=%u Height=%u Depth=%u Levels=%u Usage=%s Format=%s Pool=%s "
   1078         "ppOut=%p pSharedHandle=%p\n", This, Width, Height, Depth, Levels,
   1079         nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
   1080         nine_D3DPOOL_to_str(Pool), ppVolumeTexture, pSharedHandle);
   1081 
   1082     Usage &= D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
   1083              D3DUSAGE_SOFTWAREPROCESSING;
   1084 
   1085     *ppVolumeTexture = NULL;
   1086 
   1087     hr = NineVolumeTexture9_new(This, Width, Height, Depth, Levels,
   1088                                 Usage, Format, Pool, &tex, pSharedHandle);
   1089     if (SUCCEEDED(hr))
   1090         *ppVolumeTexture = (IDirect3DVolumeTexture9 *)tex;
   1091 
   1092     return hr;
   1093 }
   1094 
   1095 HRESULT NINE_WINAPI
   1096 NineDevice9_CreateCubeTexture( struct NineDevice9 *This,
   1097                                UINT EdgeLength,
   1098                                UINT Levels,
   1099                                DWORD Usage,
   1100                                D3DFORMAT Format,
   1101                                D3DPOOL Pool,
   1102                                IDirect3DCubeTexture9 **ppCubeTexture,
   1103                                HANDLE *pSharedHandle )
   1104 {
   1105     struct NineCubeTexture9 *tex;
   1106     HRESULT hr;
   1107 
   1108     DBG("This=%p EdgeLength=%u Levels=%u Usage=%s Format=%s Pool=%s ppOut=%p "
   1109         "pSharedHandle=%p\n", This, EdgeLength, Levels,
   1110         nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format),
   1111         nine_D3DPOOL_to_str(Pool), ppCubeTexture, pSharedHandle);
   1112 
   1113     Usage &= D3DUSAGE_AUTOGENMIPMAP | D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_DYNAMIC |
   1114              D3DUSAGE_NONSECURE | D3DUSAGE_RENDERTARGET |
   1115              D3DUSAGE_SOFTWAREPROCESSING;
   1116 
   1117     *ppCubeTexture = NULL;
   1118 
   1119     hr = NineCubeTexture9_new(This, EdgeLength, Levels, Usage, Format, Pool,
   1120                               &tex, pSharedHandle);
   1121     if (SUCCEEDED(hr))
   1122         *ppCubeTexture = (IDirect3DCubeTexture9 *)tex;
   1123 
   1124     return hr;
   1125 }
   1126 
   1127 HRESULT NINE_WINAPI
   1128 NineDevice9_CreateVertexBuffer( struct NineDevice9 *This,
   1129                                 UINT Length,
   1130                                 DWORD Usage,
   1131                                 DWORD FVF,
   1132                                 D3DPOOL Pool,
   1133                                 IDirect3DVertexBuffer9 **ppVertexBuffer,
   1134                                 HANDLE *pSharedHandle )
   1135 {
   1136     struct NineVertexBuffer9 *buf;
   1137     HRESULT hr;
   1138     D3DVERTEXBUFFER_DESC desc;
   1139 
   1140     DBG("This=%p Length=%u Usage=%x FVF=%x Pool=%u ppOut=%p pSharedHandle=%p\n",
   1141         This, Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
   1142 
   1143     user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
   1144 
   1145     desc.Format = D3DFMT_VERTEXDATA;
   1146     desc.Type = D3DRTYPE_VERTEXBUFFER;
   1147     desc.Usage = Usage &
   1148         (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
   1149          D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
   1150          D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_TEXTAPI |
   1151          D3DUSAGE_WRITEONLY);
   1152     desc.Pool = Pool;
   1153     desc.Size = Length;
   1154     desc.FVF = FVF;
   1155 
   1156     user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1157     user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
   1158 
   1159     hr = NineVertexBuffer9_new(This, &desc, &buf);
   1160     if (SUCCEEDED(hr))
   1161         *ppVertexBuffer = (IDirect3DVertexBuffer9 *)buf;
   1162     return hr;
   1163 }
   1164 
   1165 HRESULT NINE_WINAPI
   1166 NineDevice9_CreateIndexBuffer( struct NineDevice9 *This,
   1167                                UINT Length,
   1168                                DWORD Usage,
   1169                                D3DFORMAT Format,
   1170                                D3DPOOL Pool,
   1171                                IDirect3DIndexBuffer9 **ppIndexBuffer,
   1172                                HANDLE *pSharedHandle )
   1173 {
   1174     struct NineIndexBuffer9 *buf;
   1175     HRESULT hr;
   1176     D3DINDEXBUFFER_DESC desc;
   1177 
   1178     DBG("This=%p Length=%u Usage=%x Format=%s Pool=%u ppOut=%p "
   1179         "pSharedHandle=%p\n", This, Length, Usage,
   1180         d3dformat_to_string(Format), Pool, ppIndexBuffer, pSharedHandle);
   1181 
   1182     user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_NOTAVAILABLE);
   1183 
   1184     desc.Format = Format;
   1185     desc.Type = D3DRTYPE_INDEXBUFFER;
   1186     desc.Usage = Usage &
   1187         (D3DUSAGE_DONOTCLIP | D3DUSAGE_DYNAMIC | D3DUSAGE_NONSECURE |
   1188          D3DUSAGE_NPATCHES | D3DUSAGE_POINTS | D3DUSAGE_RTPATCHES |
   1189          D3DUSAGE_SOFTWAREPROCESSING | D3DUSAGE_WRITEONLY);
   1190     desc.Pool = Pool;
   1191     desc.Size = Length;
   1192 
   1193     user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1194     user_assert(desc.Usage == Usage, D3DERR_INVALIDCALL);
   1195 
   1196     hr = NineIndexBuffer9_new(This, &desc, &buf);
   1197     if (SUCCEEDED(hr))
   1198         *ppIndexBuffer = (IDirect3DIndexBuffer9 *)buf;
   1199     return hr;
   1200 }
   1201 
   1202 static HRESULT
   1203 create_zs_or_rt_surface(struct NineDevice9 *This,
   1204                         unsigned type, /* 0 = RT, 1 = ZS, 2 = plain */
   1205                         D3DPOOL Pool,
   1206                         UINT Width, UINT Height,
   1207                         D3DFORMAT Format,
   1208                         D3DMULTISAMPLE_TYPE MultiSample,
   1209                         DWORD MultisampleQuality,
   1210                         BOOL Discard_or_Lockable,
   1211                         IDirect3DSurface9 **ppSurface,
   1212                         HANDLE *pSharedHandle)
   1213 {
   1214     struct NineSurface9 *surface;
   1215     HRESULT hr;
   1216     D3DSURFACE_DESC desc;
   1217 
   1218     DBG("This=%p type=%u Pool=%s Width=%u Height=%u Format=%s MS=%u Quality=%u "
   1219         "Discard_or_Lockable=%i ppSurface=%p pSharedHandle=%p\n",
   1220         This, type, nine_D3DPOOL_to_str(Pool), Width, Height,
   1221         d3dformat_to_string(Format), MultiSample, MultisampleQuality,
   1222         Discard_or_Lockable, ppSurface, pSharedHandle);
   1223 
   1224     if (pSharedHandle)
   1225       DBG("FIXME Used shared handle! This option isn't probably handled correctly!\n");
   1226 
   1227     user_assert(Width && Height, D3DERR_INVALIDCALL);
   1228     user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
   1229 
   1230     desc.Format = Format;
   1231     desc.Type = D3DRTYPE_SURFACE;
   1232     desc.Usage = 0;
   1233     desc.Pool = Pool;
   1234     desc.MultiSampleType = MultiSample;
   1235     desc.MultiSampleQuality = MultisampleQuality;
   1236     desc.Width = Width;
   1237     desc.Height = Height;
   1238     switch (type) {
   1239     case 0: desc.Usage = D3DUSAGE_RENDERTARGET; break;
   1240     case 1: desc.Usage = D3DUSAGE_DEPTHSTENCIL; break;
   1241     default: assert(type == 2); break;
   1242     }
   1243 
   1244     hr = NineSurface9_new(This, NULL, NULL, NULL, 0, 0, 0, &desc, &surface);
   1245     if (SUCCEEDED(hr)) {
   1246         *ppSurface = (IDirect3DSurface9 *)surface;
   1247 
   1248         if (surface->base.resource && Discard_or_Lockable && (type != 1))
   1249             surface->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE;
   1250     }
   1251 
   1252     return hr;
   1253 }
   1254 
   1255 HRESULT NINE_WINAPI
   1256 NineDevice9_CreateRenderTarget( struct NineDevice9 *This,
   1257                                 UINT Width,
   1258                                 UINT Height,
   1259                                 D3DFORMAT Format,
   1260                                 D3DMULTISAMPLE_TYPE MultiSample,
   1261                                 DWORD MultisampleQuality,
   1262                                 BOOL Lockable,
   1263                                 IDirect3DSurface9 **ppSurface,
   1264                                 HANDLE *pSharedHandle )
   1265 {
   1266     *ppSurface = NULL;
   1267     return create_zs_or_rt_surface(This, 0, D3DPOOL_DEFAULT,
   1268                                    Width, Height, Format,
   1269                                    MultiSample, MultisampleQuality,
   1270                                    Lockable, ppSurface, pSharedHandle);
   1271 }
   1272 
   1273 HRESULT NINE_WINAPI
   1274 NineDevice9_CreateDepthStencilSurface( struct NineDevice9 *This,
   1275                                        UINT Width,
   1276                                        UINT Height,
   1277                                        D3DFORMAT Format,
   1278                                        D3DMULTISAMPLE_TYPE MultiSample,
   1279                                        DWORD MultisampleQuality,
   1280                                        BOOL Discard,
   1281                                        IDirect3DSurface9 **ppSurface,
   1282                                        HANDLE *pSharedHandle )
   1283 {
   1284     *ppSurface = NULL;
   1285     if (!depth_stencil_format(Format))
   1286         return D3DERR_NOTAVAILABLE;
   1287     return create_zs_or_rt_surface(This, 1, D3DPOOL_DEFAULT,
   1288                                    Width, Height, Format,
   1289                                    MultiSample, MultisampleQuality,
   1290                                    Discard, ppSurface, pSharedHandle);
   1291 }
   1292 
   1293 HRESULT NINE_WINAPI
   1294 NineDevice9_UpdateSurface( struct NineDevice9 *This,
   1295                            IDirect3DSurface9 *pSourceSurface,
   1296                            const RECT *pSourceRect,
   1297                            IDirect3DSurface9 *pDestinationSurface,
   1298                            const POINT *pDestPoint )
   1299 {
   1300     struct NineSurface9 *dst = NineSurface9(pDestinationSurface);
   1301     struct NineSurface9 *src = NineSurface9(pSourceSurface);
   1302     int copy_width, copy_height;
   1303     RECT destRect;
   1304 
   1305     DBG("This=%p pSourceSurface=%p pDestinationSurface=%p "
   1306         "pSourceRect=%p pDestPoint=%p\n", This,
   1307         pSourceSurface, pDestinationSurface, pSourceRect, pDestPoint);
   1308     if (pSourceRect)
   1309         DBG("pSourceRect = (%u,%u)-(%u,%u)\n",
   1310             pSourceRect->left, pSourceRect->top,
   1311             pSourceRect->right, pSourceRect->bottom);
   1312     if (pDestPoint)
   1313         DBG("pDestPoint = (%u,%u)\n", pDestPoint->x, pDestPoint->y);
   1314 
   1315     user_assert(dst && src, D3DERR_INVALIDCALL);
   1316 
   1317     user_assert(dst->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1318     user_assert(src->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
   1319 
   1320     user_assert(dst->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
   1321     user_assert(src->desc.MultiSampleType == D3DMULTISAMPLE_NONE, D3DERR_INVALIDCALL);
   1322 
   1323     user_assert(!src->lock_count, D3DERR_INVALIDCALL);
   1324     user_assert(!dst->lock_count, D3DERR_INVALIDCALL);
   1325 
   1326     user_assert(dst->desc.Format == src->desc.Format, D3DERR_INVALIDCALL);
   1327     user_assert(!depth_stencil_format(dst->desc.Format), D3DERR_INVALIDCALL);
   1328 
   1329     if (pSourceRect) {
   1330         copy_width = pSourceRect->right - pSourceRect->left;
   1331         copy_height = pSourceRect->bottom - pSourceRect->top;
   1332 
   1333         user_assert(pSourceRect->left >= 0 &&
   1334                     copy_width > 0 &&
   1335                     pSourceRect->right <= src->desc.Width &&
   1336                     pSourceRect->top >= 0 &&
   1337                     copy_height > 0 &&
   1338                     pSourceRect->bottom <= src->desc.Height,
   1339                     D3DERR_INVALIDCALL);
   1340     } else {
   1341         copy_width = src->desc.Width;
   1342         copy_height = src->desc.Height;
   1343     }
   1344 
   1345     destRect.right = copy_width;
   1346     destRect.bottom = copy_height;
   1347 
   1348     if (pDestPoint) {
   1349         user_assert(pDestPoint->x >= 0 && pDestPoint->y >= 0,
   1350                     D3DERR_INVALIDCALL);
   1351         destRect.right += pDestPoint->x;
   1352         destRect.bottom += pDestPoint->y;
   1353     }
   1354 
   1355     user_assert(destRect.right <= dst->desc.Width &&
   1356                 destRect.bottom <= dst->desc.Height,
   1357                 D3DERR_INVALIDCALL);
   1358 
   1359     if (compressed_format(dst->desc.Format)) {
   1360         const unsigned w = util_format_get_blockwidth(dst->base.info.format);
   1361         const unsigned h = util_format_get_blockheight(dst->base.info.format);
   1362 
   1363         if (pDestPoint) {
   1364             user_assert(!(pDestPoint->x % w) && !(pDestPoint->y % h),
   1365                         D3DERR_INVALIDCALL);
   1366         }
   1367 
   1368         if (pSourceRect) {
   1369             user_assert(!(pSourceRect->left % w) && !(pSourceRect->top % h),
   1370                         D3DERR_INVALIDCALL);
   1371         }
   1372         if (!(copy_width == src->desc.Width &&
   1373               copy_width == dst->desc.Width &&
   1374               copy_height == src->desc.Height &&
   1375               copy_height == dst->desc.Height)) {
   1376             user_assert(!(copy_width  % w) && !(copy_height % h),
   1377                         D3DERR_INVALIDCALL);
   1378         }
   1379     }
   1380 
   1381     NineSurface9_CopyMemToDefault(dst, src, pDestPoint, pSourceRect);
   1382 
   1383     return D3D_OK;
   1384 }
   1385 
   1386 HRESULT NINE_WINAPI
   1387 NineDevice9_UpdateTexture( struct NineDevice9 *This,
   1388                            IDirect3DBaseTexture9 *pSourceTexture,
   1389                            IDirect3DBaseTexture9 *pDestinationTexture )
   1390 {
   1391     struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);
   1392     struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
   1393     unsigned l, m;
   1394     unsigned last_src_level, last_dst_level;
   1395     RECT rect;
   1396 
   1397     DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
   1398         pSourceTexture, pDestinationTexture);
   1399 
   1400     user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL);
   1401     user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);
   1402 
   1403     user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1404     user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
   1405     user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
   1406     user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ||
   1407                 dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL);
   1408 
   1409     /* Spec: Failure if
   1410      * . Different formats
   1411      * . Fewer src levels than dst levels (if the opposite, only matching levels
   1412      *   are supposed to be copied)
   1413      * . Levels do not match
   1414      * DDI: Actually the above should pass because of legacy applications
   1415      * Do what you want about these, but you shouldn't crash.
   1416      * However driver can expect that the top dimension is greater for src than dst.
   1417      * Wine tests: Every combination that passes the initial checks should pass.
   1418      * . Different formats => conversion driver and format dependent.
   1419      * . 1 level, but size not matching => copy is done (and even crash if src bigger
   1420      * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied
   1421      * or if a subrect is copied).
   1422      * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect
   1423      * copied to 7x7.
   1424      *
   1425      * From these, the proposal is:
   1426      * . Different formats -> use util_format_translate to translate if possible for surfaces.
   1427      * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations
   1428      * . First level copied -> the first level such that src is smaller or equal to dst first level
   1429      * . number of levels copied -> as long as it fits and textures have levels
   1430      * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)
   1431      */
   1432 
   1433     last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level;
   1434     last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level;
   1435 
   1436     for (m = 0; m <= last_src_level; ++m) {
   1437         unsigned w = u_minify(srcb->base.info.width0, m);
   1438         unsigned h = u_minify(srcb->base.info.height0, m);
   1439         unsigned d = u_minify(srcb->base.info.depth0, m);
   1440 
   1441         if (w <= dstb->base.info.width0 &&
   1442             h <= dstb->base.info.height0 &&
   1443             d <= dstb->base.info.depth0)
   1444             break;
   1445     }
   1446     user_assert(m <= last_src_level, D3D_OK);
   1447 
   1448     last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level);
   1449 
   1450     if (dstb->base.type == D3DRTYPE_TEXTURE) {
   1451         struct NineTexture9 *dst = NineTexture9(dstb);
   1452         struct NineTexture9 *src = NineTexture9(srcb);
   1453 
   1454         if (src->dirty_rect.width == 0)
   1455             return D3D_OK;
   1456 
   1457         pipe_box_to_rect(&rect, &src->dirty_rect);
   1458         for (l = 0; l < m; ++l)
   1459             rect_minify_inclusive(&rect);
   1460 
   1461         for (l = 0; l <= last_dst_level; ++l, ++m) {
   1462             fit_rect_format_inclusive(dst->base.base.info.format,
   1463                                       &rect,
   1464                                       dst->surfaces[l]->desc.Width,
   1465                                       dst->surfaces[l]->desc.Height);
   1466             NineSurface9_CopyMemToDefault(dst->surfaces[l],
   1467                                           src->surfaces[m],
   1468                                           (POINT *)&rect,
   1469                                           &rect);
   1470             rect_minify_inclusive(&rect);
   1471         }
   1472         u_box_origin_2d(0, 0, &src->dirty_rect);
   1473     } else
   1474     if (dstb->base.type == D3DRTYPE_CUBETEXTURE) {
   1475         struct NineCubeTexture9 *dst = NineCubeTexture9(dstb);
   1476         struct NineCubeTexture9 *src = NineCubeTexture9(srcb);
   1477         unsigned z;
   1478 
   1479         /* GPUs usually have them stored as arrays of mip-mapped 2D textures. */
   1480         for (z = 0; z < 6; ++z) {
   1481             if (src->dirty_rect[z].width == 0)
   1482                 continue;
   1483 
   1484             pipe_box_to_rect(&rect, &src->dirty_rect[z]);
   1485             for (l = 0; l < m; ++l)
   1486                 rect_minify_inclusive(&rect);
   1487 
   1488             for (l = 0; l <= last_dst_level; ++l, ++m) {
   1489                 fit_rect_format_inclusive(dst->base.base.info.format,
   1490                                           &rect,
   1491                                           dst->surfaces[l * 6 + z]->desc.Width,
   1492                                           dst->surfaces[l * 6 + z]->desc.Height);
   1493                 NineSurface9_CopyMemToDefault(dst->surfaces[l * 6 + z],
   1494                                               src->surfaces[m * 6 + z],
   1495                                               (POINT *)&rect,
   1496                                               &rect);
   1497                 rect_minify_inclusive(&rect);
   1498             }
   1499             u_box_origin_2d(0, 0, &src->dirty_rect[z]);
   1500             m -= l;
   1501         }
   1502     } else
   1503     if (dstb->base.type == D3DRTYPE_VOLUMETEXTURE) {
   1504         struct NineVolumeTexture9 *dst = NineVolumeTexture9(dstb);
   1505         struct NineVolumeTexture9 *src = NineVolumeTexture9(srcb);
   1506 
   1507         if (src->dirty_box.width == 0)
   1508             return D3D_OK;
   1509         for (l = 0; l <= last_dst_level; ++l, ++m)
   1510             NineVolume9_CopyMemToDefault(dst->volumes[l],
   1511                                          src->volumes[m], 0, 0, 0, NULL);
   1512         u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box);
   1513     } else{
   1514         assert(!"invalid texture type");
   1515     }
   1516 
   1517     if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
   1518         dstb->dirty_mip = TRUE;
   1519         NineBaseTexture9_GenerateMipSubLevels(dstb);
   1520     }
   1521 
   1522     return D3D_OK;
   1523 }
   1524 
   1525 HRESULT NINE_WINAPI
   1526 NineDevice9_GetRenderTargetData( struct NineDevice9 *This,
   1527                                  IDirect3DSurface9 *pRenderTarget,
   1528                                  IDirect3DSurface9 *pDestSurface )
   1529 {
   1530     struct NineSurface9 *dst = NineSurface9(pDestSurface);
   1531     struct NineSurface9 *src = NineSurface9(pRenderTarget);
   1532 
   1533     DBG("This=%p pRenderTarget=%p pDestSurface=%p\n",
   1534         This, pRenderTarget, pDestSurface);
   1535 
   1536     user_assert(pRenderTarget && pDestSurface, D3DERR_INVALIDCALL);
   1537 
   1538     user_assert(dst->desc.Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
   1539     user_assert(src->desc.Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1540 
   1541     user_assert(dst->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
   1542     user_assert(src->desc.MultiSampleType < 2, D3DERR_INVALIDCALL);
   1543 
   1544     user_assert(src->desc.Width == dst->desc.Width, D3DERR_INVALIDCALL);
   1545     user_assert(src->desc.Height == dst->desc.Height, D3DERR_INVALIDCALL);
   1546 
   1547     user_assert(src->desc.Format != D3DFMT_NULL, D3DERR_INVALIDCALL);
   1548 
   1549     NineSurface9_CopyDefaultToMem(dst, src);
   1550 
   1551     return D3D_OK;
   1552 }
   1553 
   1554 HRESULT NINE_WINAPI
   1555 NineDevice9_GetFrontBufferData( struct NineDevice9 *This,
   1556                                 UINT iSwapChain,
   1557                                 IDirect3DSurface9 *pDestSurface )
   1558 {
   1559     DBG("This=%p iSwapChain=%u pDestSurface=%p\n", This,
   1560         iSwapChain, pDestSurface);
   1561 
   1562     user_assert(pDestSurface != NULL, D3DERR_INVALIDCALL);
   1563     user_assert(iSwapChain < This->nswapchains, D3DERR_INVALIDCALL);
   1564 
   1565     return NineSwapChain9_GetFrontBufferData(This->swapchains[iSwapChain],
   1566                                              pDestSurface);
   1567 }
   1568 
   1569 HRESULT NINE_WINAPI
   1570 NineDevice9_StretchRect( struct NineDevice9 *This,
   1571                          IDirect3DSurface9 *pSourceSurface,
   1572                          const RECT *pSourceRect,
   1573                          IDirect3DSurface9 *pDestSurface,
   1574                          const RECT *pDestRect,
   1575                          D3DTEXTUREFILTERTYPE Filter )
   1576 {
   1577     struct pipe_screen *screen = This->screen;
   1578     struct NineSurface9 *dst = NineSurface9(pDestSurface);
   1579     struct NineSurface9 *src = NineSurface9(pSourceSurface);
   1580     struct pipe_resource *dst_res = NineSurface9_GetResource(dst);
   1581     struct pipe_resource *src_res = NineSurface9_GetResource(src);
   1582     boolean zs;
   1583     struct pipe_blit_info blit;
   1584     boolean scaled, clamped, ms, flip_x = FALSE, flip_y = FALSE;
   1585 
   1586     DBG("This=%p pSourceSurface=%p pSourceRect=%p pDestSurface=%p "
   1587         "pDestRect=%p Filter=%u\n",
   1588         This, pSourceSurface, pSourceRect, pDestSurface, pDestRect, Filter);
   1589     if (pSourceRect)
   1590         DBG("pSourceRect=(%u,%u)-(%u,%u)\n",
   1591             pSourceRect->left, pSourceRect->top,
   1592             pSourceRect->right, pSourceRect->bottom);
   1593     if (pDestRect)
   1594         DBG("pDestRect=(%u,%u)-(%u,%u)\n", pDestRect->left, pDestRect->top,
   1595             pDestRect->right, pDestRect->bottom);
   1596 
   1597     user_assert(dst->base.pool == D3DPOOL_DEFAULT &&
   1598                 src->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1599     zs = util_format_is_depth_or_stencil(dst_res->format);
   1600     user_assert(!zs || !This->in_scene, D3DERR_INVALIDCALL);
   1601     user_assert(!zs || !pSourceRect ||
   1602                 (pSourceRect->left == 0 &&
   1603                  pSourceRect->top == 0 &&
   1604                  pSourceRect->right == src->desc.Width &&
   1605                  pSourceRect->bottom == src->desc.Height), D3DERR_INVALIDCALL);
   1606     user_assert(!zs || !pDestRect ||
   1607                 (pDestRect->left == 0 &&
   1608                  pDestRect->top == 0 &&
   1609                  pDestRect->right == dst->desc.Width &&
   1610                  pDestRect->bottom == dst->desc.Height), D3DERR_INVALIDCALL);
   1611     user_assert(!zs ||
   1612                 (dst->desc.Width == src->desc.Width &&
   1613                  dst->desc.Height == src->desc.Height), D3DERR_INVALIDCALL);
   1614     user_assert(zs || !util_format_is_depth_or_stencil(src_res->format),
   1615                 D3DERR_INVALIDCALL);
   1616     user_assert(!zs || dst->desc.Format == src->desc.Format,
   1617                 D3DERR_INVALIDCALL);
   1618     user_assert(screen->is_format_supported(screen, src_res->format,
   1619                                             src_res->target,
   1620                                             src_res->nr_samples,
   1621                                             PIPE_BIND_SAMPLER_VIEW),
   1622                 D3DERR_INVALIDCALL);
   1623 
   1624     /* We might want to permit these, but wine thinks we shouldn't. */
   1625     user_assert(!pDestRect ||
   1626                 (pDestRect->left <= pDestRect->right &&
   1627                  pDestRect->top <= pDestRect->bottom), D3DERR_INVALIDCALL);
   1628     user_assert(!pSourceRect ||
   1629                 (pSourceRect->left <= pSourceRect->right &&
   1630                  pSourceRect->top <= pSourceRect->bottom), D3DERR_INVALIDCALL);
   1631 
   1632     memset(&blit, 0, sizeof(blit));
   1633     blit.dst.resource = dst_res;
   1634     blit.dst.level = dst->level;
   1635     blit.dst.box.z = dst->layer;
   1636     blit.dst.box.depth = 1;
   1637     blit.dst.format = dst_res->format;
   1638     if (pDestRect) {
   1639         flip_x = pDestRect->left > pDestRect->right;
   1640         if (flip_x) {
   1641             blit.dst.box.x = pDestRect->right;
   1642             blit.dst.box.width = pDestRect->left - pDestRect->right;
   1643         } else {
   1644             blit.dst.box.x = pDestRect->left;
   1645             blit.dst.box.width = pDestRect->right - pDestRect->left;
   1646         }
   1647         flip_y = pDestRect->top > pDestRect->bottom;
   1648         if (flip_y) {
   1649             blit.dst.box.y = pDestRect->bottom;
   1650             blit.dst.box.height = pDestRect->top - pDestRect->bottom;
   1651         } else {
   1652             blit.dst.box.y = pDestRect->top;
   1653             blit.dst.box.height = pDestRect->bottom - pDestRect->top;
   1654         }
   1655     } else {
   1656         blit.dst.box.x = 0;
   1657         blit.dst.box.y = 0;
   1658         blit.dst.box.width = dst->desc.Width;
   1659         blit.dst.box.height = dst->desc.Height;
   1660     }
   1661     blit.src.resource = src_res;
   1662     blit.src.level = src->level;
   1663     blit.src.box.z = src->layer;
   1664     blit.src.box.depth = 1;
   1665     blit.src.format = src_res->format;
   1666     if (pSourceRect) {
   1667         if (flip_x ^ (pSourceRect->left > pSourceRect->right)) {
   1668             blit.src.box.x = pSourceRect->right;
   1669             blit.src.box.width = pSourceRect->left - pSourceRect->right;
   1670         } else {
   1671             blit.src.box.x = pSourceRect->left;
   1672             blit.src.box.width = pSourceRect->right - pSourceRect->left;
   1673         }
   1674         if (flip_y ^ (pSourceRect->top > pSourceRect->bottom)) {
   1675             blit.src.box.y = pSourceRect->bottom;
   1676             blit.src.box.height = pSourceRect->top - pSourceRect->bottom;
   1677         } else {
   1678             blit.src.box.y = pSourceRect->top;
   1679             blit.src.box.height = pSourceRect->bottom - pSourceRect->top;
   1680         }
   1681     } else {
   1682         blit.src.box.x = flip_x ? src->desc.Width : 0;
   1683         blit.src.box.y = flip_y ? src->desc.Height : 0;
   1684         blit.src.box.width = flip_x ? -src->desc.Width : src->desc.Width;
   1685         blit.src.box.height = flip_y ? -src->desc.Height : src->desc.Height;
   1686     }
   1687     blit.mask = zs ? PIPE_MASK_ZS : PIPE_MASK_RGBA;
   1688     blit.filter = Filter == D3DTEXF_LINEAR ?
   1689        PIPE_TEX_FILTER_LINEAR : PIPE_TEX_FILTER_NEAREST;
   1690     blit.scissor_enable = FALSE;
   1691     blit.alpha_blend = FALSE;
   1692 
   1693     /* If both of a src and dst dimension are negative, flip them. */
   1694     if (blit.dst.box.width < 0 && blit.src.box.width < 0) {
   1695         blit.dst.box.width = -blit.dst.box.width;
   1696         blit.src.box.width = -blit.src.box.width;
   1697     }
   1698     if (blit.dst.box.height < 0 && blit.src.box.height < 0) {
   1699         blit.dst.box.height = -blit.dst.box.height;
   1700         blit.src.box.height = -blit.src.box.height;
   1701     }
   1702     scaled =
   1703         blit.dst.box.width != blit.src.box.width ||
   1704         blit.dst.box.height != blit.src.box.height;
   1705 
   1706     user_assert(!scaled || dst != src, D3DERR_INVALIDCALL);
   1707     user_assert(!scaled ||
   1708                 !NineSurface9_IsOffscreenPlain(dst), D3DERR_INVALIDCALL);
   1709     user_assert(!NineSurface9_IsOffscreenPlain(dst) ||
   1710                 NineSurface9_IsOffscreenPlain(src), D3DERR_INVALIDCALL);
   1711     user_assert(NineSurface9_IsOffscreenPlain(dst) ||
   1712                 dst->desc.Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL),
   1713                 D3DERR_INVALIDCALL);
   1714     user_assert(!scaled ||
   1715                 (!util_format_is_compressed(dst->base.info.format) &&
   1716                  !util_format_is_compressed(src->base.info.format)),
   1717                 D3DERR_INVALIDCALL);
   1718 
   1719     user_warn(src == dst &&
   1720               u_box_test_intersection_2d(&blit.src.box, &blit.dst.box));
   1721 
   1722     /* Check for clipping/clamping: */
   1723     {
   1724         struct pipe_box box;
   1725         int xy;
   1726 
   1727         xy = u_box_clip_2d(&box, &blit.dst.box,
   1728                            dst->desc.Width, dst->desc.Height);
   1729         if (xy < 0)
   1730             return D3D_OK;
   1731         if (xy == 0)
   1732             xy = u_box_clip_2d(&box, &blit.src.box,
   1733                                src->desc.Width, src->desc.Height);
   1734         clamped = !!xy;
   1735     }
   1736 
   1737     ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) ||
   1738          (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality);
   1739 
   1740     if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) {
   1741         DBG("using pipe->blit()\n");
   1742         /* TODO: software scaling */
   1743         user_assert(screen->is_format_supported(screen, dst_res->format,
   1744                                                 dst_res->target,
   1745                                                 dst_res->nr_samples,
   1746                                                 zs ? PIPE_BIND_DEPTH_STENCIL :
   1747                                                 PIPE_BIND_RENDER_TARGET),
   1748                     D3DERR_INVALIDCALL);
   1749 
   1750         nine_context_blit(This, (struct NineUnknown *)dst,
   1751                           (struct NineUnknown *)src, &blit);
   1752     } else {
   1753         assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&
   1754                blit.src.box.x >= 0 && blit.src.box.y >= 0 &&
   1755                blit.dst.box.x + blit.dst.box.width <= dst->desc.Width &&
   1756                blit.src.box.x + blit.src.box.width <= src->desc.Width &&
   1757                blit.dst.box.y + blit.dst.box.height <= dst->desc.Height &&
   1758                blit.src.box.y + blit.src.box.height <= src->desc.Height);
   1759         /* Or drivers might crash ... */
   1760         DBG("Using resource_copy_region.\n");
   1761         nine_context_resource_copy_region(This, (struct NineUnknown *)dst,
   1762                                           (struct NineUnknown *)src,
   1763                                           blit.dst.resource, blit.dst.level,
   1764                                           &blit.dst.box,
   1765                                           blit.src.resource, blit.src.level,
   1766                                           &blit.src.box);
   1767     }
   1768 
   1769     /* Communicate the container it needs to update sublevels - if apply */
   1770     NineSurface9_MarkContainerDirty(dst);
   1771 
   1772     return D3D_OK;
   1773 }
   1774 
   1775 HRESULT NINE_WINAPI
   1776 NineDevice9_ColorFill( struct NineDevice9 *This,
   1777                        IDirect3DSurface9 *pSurface,
   1778                        const RECT *pRect,
   1779                        D3DCOLOR color )
   1780 {
   1781     struct NineSurface9 *surf = NineSurface9(pSurface);
   1782     unsigned x, y, w, h;
   1783 
   1784     DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,
   1785         pSurface, pRect, color);
   1786     if (pRect)
   1787         DBG("pRect=(%u,%u)-(%u,%u)\n", pRect->left, pRect->top,
   1788             pRect->right, pRect->bottom);
   1789 
   1790     user_assert(surf->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
   1791 
   1792     user_assert((surf->base.usage & D3DUSAGE_RENDERTARGET) ||
   1793                 NineSurface9_IsOffscreenPlain(surf), D3DERR_INVALIDCALL);
   1794 
   1795     user_assert(surf->desc.Format != D3DFMT_NULL, D3D_OK);
   1796 
   1797     if (pRect) {
   1798         x = pRect->left;
   1799         y = pRect->top;
   1800         w = pRect->right - pRect->left;
   1801         h = pRect->bottom - pRect->top;
   1802         /* Wine tests: */
   1803         if (compressed_format(surf->desc.Format)) {
   1804            const unsigned bw = util_format_get_blockwidth(surf->base.info.format);
   1805            const unsigned bh = util_format_get_blockheight(surf->base.info.format);
   1806 
   1807            user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh),
   1808                        D3DERR_INVALIDCALL);
   1809         }
   1810     } else{
   1811         x = 0;
   1812         y = 0;
   1813         w = surf->desc.Width;
   1814         h = surf->desc.Height;
   1815     }
   1816 
   1817     if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) {
   1818         nine_context_clear_render_target(This, surf, color, x, y, w, h);
   1819     } else {
   1820         D3DLOCKED_RECT lock;
   1821         union util_color uc;
   1822         HRESULT hr;
   1823         /* XXX: lock pRect and fix util_fill_rect */
   1824         hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD);
   1825         if (FAILED(hr))
   1826             return hr;
   1827         util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,
   1828                            surf->base.info.format, &uc);
   1829         util_fill_rect(lock.pBits, surf->base.info.format,lock.Pitch,
   1830                        x, y, w, h, &uc);
   1831         NineSurface9_UnlockRect(surf);
   1832     }
   1833 
   1834     return D3D_OK;
   1835 }
   1836 
   1837 HRESULT NINE_WINAPI
   1838 NineDevice9_CreateOffscreenPlainSurface( struct NineDevice9 *This,
   1839                                          UINT Width,
   1840                                          UINT Height,
   1841                                          D3DFORMAT Format,
   1842                                          D3DPOOL Pool,
   1843                                          IDirect3DSurface9 **ppSurface,
   1844                                          HANDLE *pSharedHandle )
   1845 {
   1846     HRESULT hr;
   1847 
   1848     DBG("This=%p Width=%u Height=%u Format=%s(0x%x) Pool=%u "
   1849         "ppSurface=%p pSharedHandle=%p\n", This,
   1850         Width, Height, d3dformat_to_string(Format), Format, Pool,
   1851         ppSurface, pSharedHandle);
   1852 
   1853     *ppSurface = NULL;
   1854     user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT
   1855                                || Pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
   1856     user_assert(Pool != D3DPOOL_MANAGED, D3DERR_INVALIDCALL);
   1857 
   1858     /* Can be used with StretchRect and ColorFill. It's also always lockable.
   1859      */
   1860     hr = create_zs_or_rt_surface(This, 2, Pool, Width, Height,
   1861                                  Format,
   1862                                  D3DMULTISAMPLE_NONE, 0,
   1863                                  TRUE,
   1864                                  ppSurface, pSharedHandle);
   1865     if (FAILED(hr))
   1866         DBG("Failed to create surface.\n");
   1867     return hr;
   1868 }
   1869 
   1870 HRESULT NINE_WINAPI
   1871 NineDevice9_SetRenderTarget( struct NineDevice9 *This,
   1872                              DWORD RenderTargetIndex,
   1873                              IDirect3DSurface9 *pRenderTarget )
   1874 {
   1875     struct NineSurface9 *rt = NineSurface9(pRenderTarget);
   1876     const unsigned i = RenderTargetIndex;
   1877 
   1878     DBG("This=%p RenderTargetIndex=%u pRenderTarget=%p\n", This,
   1879         RenderTargetIndex, pRenderTarget);
   1880 
   1881     user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
   1882     user_assert(i != 0 || pRenderTarget, D3DERR_INVALIDCALL);
   1883     user_assert(!pRenderTarget ||
   1884                 rt->desc.Usage & D3DUSAGE_RENDERTARGET, D3DERR_INVALIDCALL);
   1885 
   1886     if (i == 0) {
   1887         This->state.viewport.X = 0;
   1888         This->state.viewport.Y = 0;
   1889         This->state.viewport.Width = rt->desc.Width;
   1890         This->state.viewport.Height = rt->desc.Height;
   1891         This->state.viewport.MinZ = 0.0f;
   1892         This->state.viewport.MaxZ = 1.0f;
   1893 
   1894         This->state.scissor.minx = 0;
   1895         This->state.scissor.miny = 0;
   1896         This->state.scissor.maxx = rt->desc.Width;
   1897         This->state.scissor.maxy = rt->desc.Height;
   1898     }
   1899 
   1900     if (This->state.rt[i] != NineSurface9(pRenderTarget))
   1901         nine_bind(&This->state.rt[i], pRenderTarget);
   1902 
   1903     nine_context_set_render_target(This, i, rt);
   1904     return D3D_OK;
   1905 }
   1906 
   1907 HRESULT NINE_WINAPI
   1908 NineDevice9_GetRenderTarget( struct NineDevice9 *This,
   1909                              DWORD RenderTargetIndex,
   1910                              IDirect3DSurface9 **ppRenderTarget )
   1911 {
   1912     const unsigned i = RenderTargetIndex;
   1913 
   1914     user_assert(i < This->caps.NumSimultaneousRTs, D3DERR_INVALIDCALL);
   1915     user_assert(ppRenderTarget, D3DERR_INVALIDCALL);
   1916 
   1917     *ppRenderTarget = (IDirect3DSurface9 *)This->state.rt[i];
   1918     if (!This->state.rt[i])
   1919         return D3DERR_NOTFOUND;
   1920 
   1921     NineUnknown_AddRef(NineUnknown(This->state.rt[i]));
   1922     return D3D_OK;
   1923 }
   1924 
   1925 HRESULT NINE_WINAPI
   1926 NineDevice9_SetDepthStencilSurface( struct NineDevice9 *This,
   1927                                     IDirect3DSurface9 *pNewZStencil )
   1928 {
   1929     struct NineSurface9 *ds = NineSurface9(pNewZStencil);
   1930     DBG("This=%p pNewZStencil=%p\n", This, pNewZStencil);
   1931 
   1932     if (This->state.ds != ds) {
   1933         nine_bind(&This->state.ds, ds);
   1934         nine_context_set_depth_stencil(This, ds);
   1935     }
   1936     return D3D_OK;
   1937 }
   1938 
   1939 HRESULT NINE_WINAPI
   1940 NineDevice9_GetDepthStencilSurface( struct NineDevice9 *This,
   1941                                     IDirect3DSurface9 **ppZStencilSurface )
   1942 {
   1943     user_assert(ppZStencilSurface, D3DERR_INVALIDCALL);
   1944 
   1945     *ppZStencilSurface = (IDirect3DSurface9 *)This->state.ds;
   1946     if (!This->state.ds)
   1947         return D3DERR_NOTFOUND;
   1948 
   1949     NineUnknown_AddRef(NineUnknown(This->state.ds));
   1950     return D3D_OK;
   1951 }
   1952 
   1953 HRESULT NINE_WINAPI
   1954 NineDevice9_BeginScene( struct NineDevice9 *This )
   1955 {
   1956     DBG("This=%p\n", This);
   1957     user_assert(!This->in_scene, D3DERR_INVALIDCALL);
   1958     This->in_scene = TRUE;
   1959     /* Do we want to do anything else here ? */
   1960     return D3D_OK;
   1961 }
   1962 
   1963 HRESULT NINE_WINAPI
   1964 NineDevice9_EndScene( struct NineDevice9 *This )
   1965 {
   1966     DBG("This=%p\n", This);
   1967     user_assert(This->in_scene, D3DERR_INVALIDCALL);
   1968     This->in_scene = FALSE;
   1969     return D3D_OK;
   1970 }
   1971 
   1972 HRESULT NINE_WINAPI
   1973 NineDevice9_Clear( struct NineDevice9 *This,
   1974                    DWORD Count,
   1975                    const D3DRECT *pRects,
   1976                    DWORD Flags,
   1977                    D3DCOLOR Color,
   1978                    float Z,
   1979                    DWORD Stencil )
   1980 {
   1981     struct NineSurface9 *zsbuf_surf = This->state.ds;
   1982 
   1983     DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n",
   1984         This, Count, pRects, Flags, Color, Z, Stencil);
   1985 
   1986     user_assert(This->state.ds || !(Flags & NINED3DCLEAR_DEPTHSTENCIL),
   1987                 D3DERR_INVALIDCALL);
   1988     user_assert(!(Flags & D3DCLEAR_STENCIL) ||
   1989                 (zsbuf_surf &&
   1990                  util_format_is_depth_and_stencil(zsbuf_surf->base.info.format)),
   1991                 D3DERR_INVALIDCALL);
   1992 #ifdef NINE_STRICT
   1993     user_assert((Count && pRects) || (!Count && !pRects), D3DERR_INVALIDCALL);
   1994 #else
   1995     user_warn((pRects && !Count) || (!pRects && Count));
   1996     if (pRects && !Count)
   1997         return D3D_OK;
   1998     if (!pRects)
   1999         Count = 0;
   2000 #endif
   2001 
   2002     nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil);
   2003     return D3D_OK;
   2004 }
   2005 
   2006 HRESULT NINE_WINAPI
   2007 NineDevice9_SetTransform( struct NineDevice9 *This,
   2008                           D3DTRANSFORMSTATETYPE State,
   2009                           const D3DMATRIX *pMatrix )
   2010 {
   2011     struct nine_state *state = This->update;
   2012     D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE);
   2013 
   2014     DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);
   2015 
   2016     user_assert(M, D3DERR_INVALIDCALL);
   2017 
   2018     *M = *pMatrix;
   2019     if (unlikely(This->is_recording)) {
   2020         state->ff.changed.transform[State / 32] |= 1 << (State % 32);
   2021         state->changed.group |= NINE_STATE_FF;
   2022     } else
   2023         nine_context_set_transform(This, State, pMatrix);
   2024 
   2025     return D3D_OK;
   2026 }
   2027 
   2028 HRESULT NINE_WINAPI
   2029 NineDevice9_GetTransform( struct NineDevice9 *This,
   2030                           D3DTRANSFORMSTATETYPE State,
   2031                           D3DMATRIX *pMatrix )
   2032 {
   2033     D3DMATRIX *M = nine_state_access_transform(&This->state.ff, State, FALSE);
   2034     user_assert(M, D3DERR_INVALIDCALL);
   2035     *pMatrix = *M;
   2036     return D3D_OK;
   2037 }
   2038 
   2039 HRESULT NINE_WINAPI
   2040 NineDevice9_MultiplyTransform( struct NineDevice9 *This,
   2041                                D3DTRANSFORMSTATETYPE State,
   2042                                const D3DMATRIX *pMatrix )
   2043 {
   2044     struct nine_state *state = This->update;
   2045     D3DMATRIX T;
   2046     D3DMATRIX *M = nine_state_access_transform(&state->ff, State, TRUE);
   2047 
   2048     DBG("This=%p State=%d pMatrix=%p\n", This, State, pMatrix);
   2049 
   2050     user_assert(M, D3DERR_INVALIDCALL);
   2051 
   2052     nine_d3d_matrix_matrix_mul(&T, pMatrix, M);
   2053     return NineDevice9_SetTransform(This, State, &T);
   2054 }
   2055 
   2056 HRESULT NINE_WINAPI
   2057 NineDevice9_SetViewport( struct NineDevice9 *This,
   2058                          const D3DVIEWPORT9 *pViewport )
   2059 {
   2060     struct nine_state *state = This->update;
   2061 
   2062     DBG("X=%u Y=%u W=%u H=%u MinZ=%f MaxZ=%f\n",
   2063         pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height,
   2064         pViewport->MinZ, pViewport->MaxZ);
   2065 
   2066     state->viewport = *pViewport;
   2067     nine_context_set_viewport(This, pViewport);
   2068 
   2069     return D3D_OK;
   2070 }
   2071 
   2072 HRESULT NINE_WINAPI
   2073 NineDevice9_GetViewport( struct NineDevice9 *This,
   2074                          D3DVIEWPORT9 *pViewport )
   2075 {
   2076     *pViewport = This->state.viewport;
   2077     return D3D_OK;
   2078 }
   2079 
   2080 HRESULT NINE_WINAPI
   2081 NineDevice9_SetMaterial( struct NineDevice9 *This,
   2082                          const D3DMATERIAL9 *pMaterial )
   2083 {
   2084     struct nine_state *state = This->update;
   2085 
   2086     DBG("This=%p pMaterial=%p\n", This, pMaterial);
   2087     if (pMaterial)
   2088         nine_dump_D3DMATERIAL9(DBG_FF, pMaterial);
   2089 
   2090     user_assert(pMaterial, E_POINTER);
   2091 
   2092     state->ff.material = *pMaterial;
   2093     if (unlikely(This->is_recording))
   2094         state->changed.group |= NINE_STATE_FF_MATERIAL;
   2095     else
   2096         nine_context_set_material(This, pMaterial);
   2097 
   2098     return D3D_OK;
   2099 }
   2100 
   2101 HRESULT NINE_WINAPI
   2102 NineDevice9_GetMaterial( struct NineDevice9 *This,
   2103                          D3DMATERIAL9 *pMaterial )
   2104 {
   2105     user_assert(pMaterial, E_POINTER);
   2106     *pMaterial = This->state.ff.material;
   2107     return D3D_OK;
   2108 }
   2109 
   2110 HRESULT NINE_WINAPI
   2111 NineDevice9_SetLight( struct NineDevice9 *This,
   2112                       DWORD Index,
   2113                       const D3DLIGHT9 *pLight )
   2114 {
   2115     struct nine_state *state = This->update;
   2116     HRESULT hr;
   2117 
   2118     DBG("This=%p Index=%u pLight=%p\n", This, Index, pLight);
   2119     if (pLight)
   2120         nine_dump_D3DLIGHT9(DBG_FF, pLight);
   2121 
   2122     user_assert(pLight, D3DERR_INVALIDCALL);
   2123     user_assert(pLight->Type < NINED3DLIGHT_INVALID, D3DERR_INVALIDCALL);
   2124 
   2125     user_assert(Index < NINE_MAX_LIGHTS, D3DERR_INVALIDCALL); /* sanity */
   2126 
   2127     hr = nine_state_set_light(&state->ff, Index, pLight);
   2128     if (hr != D3D_OK)
   2129         return hr;
   2130 
   2131     if (pLight->Type != D3DLIGHT_DIRECTIONAL &&
   2132         pLight->Attenuation0 == 0.0f &&
   2133         pLight->Attenuation1 == 0.0f &&
   2134         pLight->Attenuation2 == 0.0f) {
   2135         DBG("Warning: all D3DLIGHT9.Attenuation[i] are 0\n");
   2136     }
   2137 
   2138     if (unlikely(This->is_recording))
   2139         state->changed.group |= NINE_STATE_FF_LIGHTING;
   2140     else
   2141         nine_context_set_light(This, Index, pLight);
   2142 
   2143     return D3D_OK;
   2144 }
   2145 
   2146 HRESULT NINE_WINAPI
   2147 NineDevice9_GetLight( struct NineDevice9 *This,
   2148                       DWORD Index,
   2149                       D3DLIGHT9 *pLight )
   2150 {
   2151     const struct nine_state *state = &This->state;
   2152 
   2153     user_assert(pLight, D3DERR_INVALIDCALL);
   2154     user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
   2155     user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
   2156                 D3DERR_INVALIDCALL);
   2157 
   2158     *pLight = state->ff.light[Index];
   2159 
   2160     return D3D_OK;
   2161 }
   2162 
   2163 HRESULT NINE_WINAPI
   2164 NineDevice9_LightEnable( struct NineDevice9 *This,
   2165                          DWORD Index,
   2166                          BOOL Enable )
   2167 {
   2168     struct nine_state *state = This->update;
   2169 
   2170     DBG("This=%p Index=%u Enable=%i\n", This, Index, Enable);
   2171 
   2172     if (Index >= state->ff.num_lights ||
   2173         state->ff.light[Index].Type == NINED3DLIGHT_INVALID) {
   2174         /* This should create a default light. */
   2175         D3DLIGHT9 light;
   2176         memset(&light, 0, sizeof(light));
   2177         light.Type = D3DLIGHT_DIRECTIONAL;
   2178         light.Diffuse.r = 1.0f;
   2179         light.Diffuse.g = 1.0f;
   2180         light.Diffuse.b = 1.0f;
   2181         light.Direction.z = 1.0f;
   2182         NineDevice9_SetLight(This, Index, &light);
   2183     }
   2184 
   2185     nine_state_light_enable(&state->ff, &state->changed.group, Index, Enable);
   2186     if (likely(!This->is_recording))
   2187         nine_context_light_enable(This, Index, Enable);
   2188 
   2189     return D3D_OK;
   2190 }
   2191 
   2192 HRESULT NINE_WINAPI
   2193 NineDevice9_GetLightEnable( struct NineDevice9 *This,
   2194                             DWORD Index,
   2195                             BOOL *pEnable )
   2196 {
   2197     const struct nine_state *state = &This->state;
   2198     unsigned i;
   2199 
   2200     user_assert(Index < state->ff.num_lights, D3DERR_INVALIDCALL);
   2201     user_assert(state->ff.light[Index].Type < NINED3DLIGHT_INVALID,
   2202                 D3DERR_INVALIDCALL);
   2203 
   2204     for (i = 0; i < state->ff.num_lights_active; ++i)
   2205         if (state->ff.active_light[i] == Index)
   2206             break;
   2207 
   2208     *pEnable = i != state->ff.num_lights_active ? 128 : 0; // Taken from wine
   2209 
   2210     return D3D_OK;
   2211 }
   2212 
   2213 HRESULT NINE_WINAPI
   2214 NineDevice9_SetClipPlane( struct NineDevice9 *This,
   2215                           DWORD Index,
   2216                           const float *pPlane )
   2217 {
   2218     struct nine_state *state = This->update;
   2219 
   2220     user_assert(pPlane, D3DERR_INVALIDCALL);
   2221 
   2222     DBG("This=%p Index=%u pPlane=%f %f %f %f\n", This, Index,
   2223         pPlane[0], pPlane[1],
   2224         pPlane[2], pPlane[3]);
   2225 
   2226     user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
   2227 
   2228     memcpy(&state->clip.ucp[Index][0], pPlane, sizeof(state->clip.ucp[0]));
   2229     if (unlikely(This->is_recording))
   2230         state->changed.ucp |= 1 << Index;
   2231     else
   2232         nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane);
   2233 
   2234     return D3D_OK;
   2235 }
   2236 
   2237 HRESULT NINE_WINAPI
   2238 NineDevice9_GetClipPlane( struct NineDevice9 *This,
   2239                           DWORD Index,
   2240                           float *pPlane )
   2241 {
   2242     const struct nine_state *state = &This->state;
   2243 
   2244     user_assert(Index < PIPE_MAX_CLIP_PLANES, D3DERR_INVALIDCALL);
   2245 
   2246     memcpy(pPlane, &state->clip.ucp[Index][0], sizeof(state->clip.ucp[0]));
   2247     return D3D_OK;
   2248 }
   2249 
   2250 HRESULT NINE_WINAPI
   2251 NineDevice9_SetRenderState( struct NineDevice9 *This,
   2252                             D3DRENDERSTATETYPE State,
   2253                             DWORD Value )
   2254 {
   2255     struct nine_state *state = This->update;
   2256 
   2257     DBG("This=%p State=%u(%s) Value=%08x\n", This,
   2258         State, nine_d3drs_to_string(State), Value);
   2259 
   2260     user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL);
   2261 
   2262     if (unlikely(This->is_recording)) {
   2263         state->rs_advertised[State] = Value;
   2264         /* only need to record changed render states for stateblocks */
   2265         state->changed.rs[State / 32] |= 1 << (State % 32);
   2266         state->changed.group |= nine_render_state_group[State];
   2267         return D3D_OK;
   2268     }
   2269 
   2270     if (state->rs_advertised[State] == Value)
   2271         return D3D_OK;
   2272 
   2273     state->rs_advertised[State] = Value;
   2274     nine_context_set_render_state(This, State, Value);
   2275 
   2276     return D3D_OK;
   2277 }
   2278 
   2279 HRESULT NINE_WINAPI
   2280 NineDevice9_GetRenderState( struct NineDevice9 *This,
   2281                             D3DRENDERSTATETYPE State,
   2282                             DWORD *pValue )
   2283 {
   2284     user_assert(State < D3DRS_COUNT, D3DERR_INVALIDCALL);
   2285 
   2286     *pValue = This->state.rs_advertised[State];
   2287     return D3D_OK;
   2288 }
   2289 
   2290 HRESULT NINE_WINAPI
   2291 NineDevice9_CreateStateBlock( struct NineDevice9 *This,
   2292                               D3DSTATEBLOCKTYPE Type,
   2293                               IDirect3DStateBlock9 **ppSB )
   2294 {
   2295     struct NineStateBlock9 *nsb;
   2296     struct nine_state *dst;
   2297     HRESULT hr;
   2298     enum nine_stateblock_type type;
   2299     unsigned s;
   2300 
   2301     DBG("This=%p Type=%u ppSB=%p\n", This, Type, ppSB);
   2302 
   2303     user_assert(Type == D3DSBT_ALL ||
   2304                 Type == D3DSBT_VERTEXSTATE ||
   2305                 Type == D3DSBT_PIXELSTATE, D3DERR_INVALIDCALL);
   2306 
   2307     switch (Type) {
   2308     case D3DSBT_VERTEXSTATE: type = NINESBT_VERTEXSTATE; break;
   2309     case D3DSBT_PIXELSTATE:  type = NINESBT_PIXELSTATE; break;
   2310     default:
   2311        type = NINESBT_ALL;
   2312        break;
   2313     }
   2314 
   2315     hr = NineStateBlock9_new(This, &nsb, type);
   2316     if (FAILED(hr))
   2317        return hr;
   2318     *ppSB = (IDirect3DStateBlock9 *)nsb;
   2319     dst = &nsb->state;
   2320 
   2321     dst->changed.group =
   2322        NINE_STATE_TEXTURE |
   2323        NINE_STATE_SAMPLER;
   2324 
   2325     if (Type == D3DSBT_ALL || Type == D3DSBT_VERTEXSTATE) {
   2326        dst->changed.group |=
   2327            NINE_STATE_FF_LIGHTING |
   2328            NINE_STATE_VS | NINE_STATE_VS_CONST |
   2329            NINE_STATE_VDECL;
   2330        /* TODO: texture/sampler state */
   2331        memcpy(dst->changed.rs,
   2332               nine_render_states_vertex, sizeof(dst->changed.rs));
   2333        nine_ranges_insert(&dst->changed.vs_const_f, 0, This->may_swvp ? NINE_MAX_CONST_F_SWVP : This->max_vs_const_f,
   2334                           &This->range_pool);
   2335        nine_ranges_insert(&dst->changed.vs_const_i, 0, This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I,
   2336                           &This->range_pool);
   2337        nine_ranges_insert(&dst->changed.vs_const_b, 0, This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B,
   2338                           &This->range_pool);
   2339        for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
   2340            dst->changed.sampler[s] |= 1 << D3DSAMP_DMAPOFFSET;
   2341        if (This->state.ff.num_lights) {
   2342            dst->ff.num_lights = This->state.ff.num_lights;
   2343            /* zero'd -> light type won't be NINED3DLIGHT_INVALID, so
   2344             * all currently existing lights will be captured
   2345             */
   2346            dst->ff.light = CALLOC(This->state.ff.num_lights,
   2347                                   sizeof(D3DLIGHT9));
   2348            if (!dst->ff.light) {
   2349                nine_bind(ppSB, NULL);
   2350                return E_OUTOFMEMORY;
   2351            }
   2352        }
   2353     }
   2354     if (Type == D3DSBT_ALL || Type == D3DSBT_PIXELSTATE) {
   2355        dst->changed.group |=
   2356           NINE_STATE_PS | NINE_STATE_PS_CONST | NINE_STATE_BLEND |
   2357           NINE_STATE_FF_OTHER | NINE_STATE_FF_PSSTAGES | NINE_STATE_PS_CONST |
   2358           NINE_STATE_FB | NINE_STATE_DSA | NINE_STATE_MULTISAMPLE |
   2359           NINE_STATE_RASTERIZER | NINE_STATE_STENCIL_REF;
   2360        memcpy(dst->changed.rs,
   2361               nine_render_states_pixel, sizeof(dst->changed.rs));
   2362        nine_ranges_insert(&dst->changed.ps_const_f, 0, This->max_ps_const_f,
   2363                           &This->range_pool);
   2364        dst->changed.ps_const_i = 0xffff;
   2365        dst->changed.ps_const_b = 0xffff;
   2366        for (s = 0; s < NINE_MAX_SAMPLERS; ++s)
   2367            dst->changed.sampler[s] |= 0x1ffe;
   2368        for (s = 0; s < NINE_MAX_TEXTURE_STAGES; ++s) {
   2369            dst->ff.changed.tex_stage[s][0] |= 0xffffffff;
   2370            dst->ff.changed.tex_stage[s][1] |= 0xffffffff;
   2371        }
   2372     }
   2373     if (Type == D3DSBT_ALL) {
   2374        dst->changed.group |=
   2375           NINE_STATE_VIEWPORT |
   2376           NINE_STATE_SCISSOR |
   2377           NINE_STATE_RASTERIZER |
   2378           NINE_STATE_BLEND |
   2379           NINE_STATE_DSA |
   2380           NINE_STATE_IDXBUF |
   2381           NINE_STATE_MATERIAL |
   2382           NINE_STATE_BLEND_COLOR |
   2383           NINE_STATE_SAMPLE_MASK;
   2384        memset(dst->changed.rs, ~0, (D3DRS_COUNT / 32) * sizeof(uint32_t));
   2385        dst->changed.rs[D3DRS_LAST / 32] |= (1 << (D3DRS_COUNT % 32)) - 1;
   2386        dst->changed.vtxbuf = (1ULL << This->caps.MaxStreams) - 1;
   2387        dst->changed.stream_freq = dst->changed.vtxbuf;
   2388        dst->changed.ucp = (1 << PIPE_MAX_CLIP_PLANES) - 1;
   2389        dst->changed.texture = (1 << NINE_MAX_SAMPLERS) - 1;
   2390     }
   2391     NineStateBlock9_Capture(NineStateBlock9(*ppSB));
   2392 
   2393     /* TODO: fixed function state */
   2394 
   2395     return D3D_OK;
   2396 }
   2397 
   2398 HRESULT NINE_WINAPI
   2399 NineDevice9_BeginStateBlock( struct NineDevice9 *This )
   2400 {
   2401     HRESULT hr;
   2402 
   2403     DBG("This=%p\n", This);
   2404 
   2405     user_assert(!This->record, D3DERR_INVALIDCALL);
   2406 
   2407     hr = NineStateBlock9_new(This, &This->record, NINESBT_CUSTOM);
   2408     if (FAILED(hr))
   2409         return hr;
   2410     NineUnknown_ConvertRefToBind(NineUnknown(This->record));
   2411 
   2412     This->update = &This->record->state;
   2413     This->is_recording = TRUE;
   2414 
   2415     return D3D_OK;
   2416 }
   2417 
   2418 HRESULT NINE_WINAPI
   2419 NineDevice9_EndStateBlock( struct NineDevice9 *This,
   2420                            IDirect3DStateBlock9 **ppSB )
   2421 {
   2422     DBG("This=%p ppSB=%p\n", This, ppSB);
   2423 
   2424     user_assert(This->record, D3DERR_INVALIDCALL);
   2425 
   2426     This->update = &This->state;
   2427     This->is_recording = FALSE;
   2428 
   2429     NineUnknown_AddRef(NineUnknown(This->record));
   2430     *ppSB = (IDirect3DStateBlock9 *)This->record;
   2431     NineUnknown_Unbind(NineUnknown(This->record));
   2432     This->record = NULL;
   2433 
   2434     return D3D_OK;
   2435 }
   2436 
   2437 HRESULT NINE_WINAPI
   2438 NineDevice9_SetClipStatus( struct NineDevice9 *This,
   2439                            const D3DCLIPSTATUS9 *pClipStatus )
   2440 {
   2441     STUB(D3DERR_INVALIDCALL);
   2442 }
   2443 
   2444 HRESULT NINE_WINAPI
   2445 NineDevice9_GetClipStatus( struct NineDevice9 *This,
   2446                            D3DCLIPSTATUS9 *pClipStatus )
   2447 {
   2448     STUB(D3DERR_INVALIDCALL);
   2449 }
   2450 
   2451 HRESULT NINE_WINAPI
   2452 NineDevice9_GetTexture( struct NineDevice9 *This,
   2453                         DWORD Stage,
   2454                         IDirect3DBaseTexture9 **ppTexture )
   2455 {
   2456     user_assert(Stage < This->caps.MaxSimultaneousTextures ||
   2457                 Stage == D3DDMAPSAMPLER ||
   2458                 (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
   2459                  Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
   2460     user_assert(ppTexture, D3DERR_INVALIDCALL);
   2461 
   2462     if (Stage >= D3DDMAPSAMPLER)
   2463         Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
   2464 
   2465     *ppTexture = (IDirect3DBaseTexture9 *)This->state.texture[Stage];
   2466 
   2467     if (This->state.texture[Stage])
   2468         NineUnknown_AddRef(NineUnknown(This->state.texture[Stage]));
   2469     return D3D_OK;
   2470 }
   2471 
   2472 HRESULT NINE_WINAPI
   2473 NineDevice9_SetTexture( struct NineDevice9 *This,
   2474                         DWORD Stage,
   2475                         IDirect3DBaseTexture9 *pTexture )
   2476 {
   2477     struct nine_state *state = This->update;
   2478     struct NineBaseTexture9 *tex = NineBaseTexture9(pTexture);
   2479     struct NineBaseTexture9 *old;
   2480 
   2481     DBG("This=%p Stage=%u pTexture=%p\n", This, Stage, pTexture);
   2482 
   2483     user_assert(Stage < This->caps.MaxSimultaneousTextures ||
   2484                 Stage == D3DDMAPSAMPLER ||
   2485                 (Stage >= D3DVERTEXTEXTURESAMPLER0 &&
   2486                  Stage <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
   2487     user_assert(!tex || (tex->base.pool != D3DPOOL_SCRATCH &&
   2488                 tex->base.pool != D3DPOOL_SYSTEMMEM), D3DERR_INVALIDCALL);
   2489 
   2490     if (Stage >= D3DDMAPSAMPLER)
   2491         Stage = Stage - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
   2492 
   2493     if (This->is_recording) {
   2494         state->changed.texture |= 1 << Stage;
   2495         state->changed.group |= NINE_STATE_TEXTURE;
   2496         nine_bind(&state->texture[Stage], pTexture);
   2497         return D3D_OK;
   2498     }
   2499 
   2500     old = state->texture[Stage];
   2501     if (old == tex)
   2502         return D3D_OK;
   2503 
   2504     NineBindTextureToDevice(This, &state->texture[Stage], tex);
   2505 
   2506     nine_context_set_texture(This, Stage, tex);
   2507 
   2508     return D3D_OK;
   2509 }
   2510 
   2511 HRESULT NINE_WINAPI
   2512 NineDevice9_GetTextureStageState( struct NineDevice9 *This,
   2513                                   DWORD Stage,
   2514                                   D3DTEXTURESTAGESTATETYPE Type,
   2515                                   DWORD *pValue )
   2516 {
   2517     const struct nine_state *state = &This->state;
   2518 
   2519     user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);
   2520     user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
   2521 
   2522     *pValue = state->ff.tex_stage[Stage][Type];
   2523 
   2524     return D3D_OK;
   2525 }
   2526 
   2527 HRESULT NINE_WINAPI
   2528 NineDevice9_SetTextureStageState( struct NineDevice9 *This,
   2529                                   DWORD Stage,
   2530                                   D3DTEXTURESTAGESTATETYPE Type,
   2531                                   DWORD Value )
   2532 {
   2533     struct nine_state *state = This->update;
   2534 
   2535     DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
   2536     nine_dump_D3DTSS_value(DBG_FF, Type, Value);
   2537 
   2538     user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);
   2539     user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
   2540 
   2541     state->ff.tex_stage[Stage][Type] = Value;
   2542 
   2543     if (unlikely(This->is_recording)) {
   2544         if (Type == D3DTSS_TEXTURETRANSFORMFLAGS)
   2545             state->changed.group |= NINE_STATE_PS1X_SHADER;
   2546         state->changed.group |= NINE_STATE_FF_PSSTAGES;
   2547         state->ff.changed.tex_stage[Stage][Type / 32] |= 1 << (Type % 32);
   2548     } else
   2549         nine_context_set_texture_stage_state(This, Stage, Type, Value);
   2550 
   2551     return D3D_OK;
   2552 }
   2553 
   2554 HRESULT NINE_WINAPI
   2555 NineDevice9_GetSamplerState( struct NineDevice9 *This,
   2556                              DWORD Sampler,
   2557                              D3DSAMPLERSTATETYPE Type,
   2558                              DWORD *pValue )
   2559 {
   2560     user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
   2561                 Sampler == D3DDMAPSAMPLER ||
   2562                 (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
   2563                  Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
   2564 
   2565     if (Sampler >= D3DDMAPSAMPLER)
   2566         Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
   2567 
   2568     *pValue = This->state.samp_advertised[Sampler][Type];
   2569     return D3D_OK;
   2570 }
   2571 
   2572 HRESULT NINE_WINAPI
   2573 NineDevice9_SetSamplerState( struct NineDevice9 *This,
   2574                              DWORD Sampler,
   2575                              D3DSAMPLERSTATETYPE Type,
   2576                              DWORD Value )
   2577 {
   2578     struct nine_state *state = This->update;
   2579 
   2580     DBG("This=%p Sampler=%u Type=%s Value=%08x\n", This,
   2581         Sampler, nine_D3DSAMP_to_str(Type), Value);
   2582 
   2583     user_assert(Sampler < This->caps.MaxSimultaneousTextures ||
   2584                 Sampler == D3DDMAPSAMPLER ||
   2585                 (Sampler >= D3DVERTEXTEXTURESAMPLER0 &&
   2586                  Sampler <= D3DVERTEXTEXTURESAMPLER3), D3DERR_INVALIDCALL);
   2587 
   2588     if (Sampler >= D3DDMAPSAMPLER)
   2589         Sampler = Sampler - D3DDMAPSAMPLER + NINE_MAX_SAMPLERS_PS;
   2590 
   2591     if (unlikely(This->is_recording)) {
   2592         state->samp_advertised[Sampler][Type] = Value;
   2593         state->changed.group |= NINE_STATE_SAMPLER;
   2594         state->changed.sampler[Sampler] |= 1 << Type;
   2595         return D3D_OK;
   2596     }
   2597 
   2598     if (state->samp_advertised[Sampler][Type] == Value)
   2599         return D3D_OK;
   2600 
   2601     state->samp_advertised[Sampler][Type] = Value;
   2602     nine_context_set_sampler_state(This, Sampler, Type, Value);
   2603 
   2604     return D3D_OK;
   2605 }
   2606 
   2607 HRESULT NINE_WINAPI
   2608 NineDevice9_ValidateDevice( struct NineDevice9 *This,
   2609                             DWORD *pNumPasses )
   2610 {
   2611     const struct nine_state *state = &This->state;
   2612     unsigned i;
   2613     unsigned w = 0, h = 0;
   2614 
   2615     DBG("This=%p pNumPasses=%p\n", This, pNumPasses);
   2616 
   2617     for (i = 0; i < ARRAY_SIZE(state->samp_advertised); ++i) {
   2618         if (state->samp_advertised[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||
   2619             state->samp_advertised[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)
   2620             return D3DERR_UNSUPPORTEDTEXTUREFILTER;
   2621     }
   2622 
   2623     for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
   2624         if (!state->rt[i])
   2625             continue;
   2626         if (w == 0) {
   2627             w = state->rt[i]->desc.Width;
   2628             h = state->rt[i]->desc.Height;
   2629         } else
   2630         if (state->rt[i]->desc.Width != w || state->rt[i]->desc.Height != h) {
   2631             return D3DERR_CONFLICTINGRENDERSTATE;
   2632         }
   2633     }
   2634     if (state->ds &&
   2635         (state->rs_advertised[D3DRS_ZENABLE] || state->rs_advertised[D3DRS_STENCILENABLE])) {
   2636         if (w != 0 &&
   2637             (state->ds->desc.Width != w || state->ds->desc.Height != h))
   2638             return D3DERR_CONFLICTINGRENDERSTATE;
   2639     }
   2640 
   2641     if (pNumPasses)
   2642         *pNumPasses = 1;
   2643 
   2644     return D3D_OK;
   2645 }
   2646 
   2647 HRESULT NINE_WINAPI
   2648 NineDevice9_SetPaletteEntries( struct NineDevice9 *This,
   2649                                UINT PaletteNumber,
   2650                                const PALETTEENTRY *pEntries )
   2651 {
   2652     STUB(D3D_OK); /* like wine */
   2653 }
   2654 
   2655 HRESULT NINE_WINAPI
   2656 NineDevice9_GetPaletteEntries( struct NineDevice9 *This,
   2657                                UINT PaletteNumber,
   2658                                PALETTEENTRY *pEntries )
   2659 {
   2660     STUB(D3DERR_INVALIDCALL);
   2661 }
   2662 
   2663 HRESULT NINE_WINAPI
   2664 NineDevice9_SetCurrentTexturePalette( struct NineDevice9 *This,
   2665                                       UINT PaletteNumber )
   2666 {
   2667     STUB(D3D_OK); /* like wine */
   2668 }
   2669 
   2670 HRESULT NINE_WINAPI
   2671 NineDevice9_GetCurrentTexturePalette( struct NineDevice9 *This,
   2672                                       UINT *PaletteNumber )
   2673 {
   2674     STUB(D3DERR_INVALIDCALL);
   2675 }
   2676 
   2677 HRESULT NINE_WINAPI
   2678 NineDevice9_SetScissorRect( struct NineDevice9 *This,
   2679                             const RECT *pRect )
   2680 {
   2681     struct nine_state *state = This->update;
   2682 
   2683     DBG("x=(%u..%u) y=(%u..%u)\n",
   2684         pRect->left, pRect->top, pRect->right, pRect->bottom);
   2685 
   2686     state->scissor.minx = pRect->left;
   2687     state->scissor.miny = pRect->top;
   2688     state->scissor.maxx = pRect->right;
   2689     state->scissor.maxy = pRect->bottom;
   2690 
   2691     if (unlikely(This->is_recording))
   2692         state->changed.group |= NINE_STATE_SCISSOR;
   2693     else
   2694         nine_context_set_scissor(This, &state->scissor);
   2695 
   2696     return D3D_OK;
   2697 }
   2698 
   2699 HRESULT NINE_WINAPI
   2700 NineDevice9_GetScissorRect( struct NineDevice9 *This,
   2701                             RECT *pRect )
   2702 {
   2703     pRect->left   = This->state.scissor.minx;
   2704     pRect->top    = This->state.scissor.miny;
   2705     pRect->right  = This->state.scissor.maxx;
   2706     pRect->bottom = This->state.scissor.maxy;
   2707 
   2708     return D3D_OK;
   2709 }
   2710 
   2711 HRESULT NINE_WINAPI
   2712 NineDevice9_SetSoftwareVertexProcessing( struct NineDevice9 *This,
   2713                                          BOOL bSoftware )
   2714 {
   2715     if (This->params.BehaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING) {
   2716         This->swvp = bSoftware;
   2717         nine_context_set_swvp(This, bSoftware);
   2718         return D3D_OK;
   2719     } else
   2720         return D3DERR_INVALIDCALL; /* msdn. TODO: check in practice */
   2721 }
   2722 
   2723 BOOL NINE_WINAPI
   2724 NineDevice9_GetSoftwareVertexProcessing( struct NineDevice9 *This )
   2725 {
   2726     return This->swvp;
   2727 }
   2728 
   2729 HRESULT NINE_WINAPI
   2730 NineDevice9_SetNPatchMode( struct NineDevice9 *This,
   2731                            float nSegments )
   2732 {
   2733     return D3D_OK; /* Nothing to do because we don't advertise NPatch support */
   2734 }
   2735 
   2736 float NINE_WINAPI
   2737 NineDevice9_GetNPatchMode( struct NineDevice9 *This )
   2738 {
   2739     STUB(0);
   2740 }
   2741 
   2742 /* TODO: only go through dirty textures */
   2743 static void
   2744 validate_textures(struct NineDevice9 *device)
   2745 {
   2746     struct NineBaseTexture9 *tex, *ptr;
   2747     LIST_FOR_EACH_ENTRY_SAFE(tex, ptr, &device->update_textures, list) {
   2748         list_delinit(&tex->list);
   2749         NineBaseTexture9_Validate(tex);
   2750     }
   2751 }
   2752 
   2753 static void
   2754 update_managed_buffers(struct NineDevice9 *device)
   2755 {
   2756     struct NineBuffer9 *buf, *ptr;
   2757     LIST_FOR_EACH_ENTRY_SAFE(buf, ptr, &device->update_buffers, managed.list) {
   2758         list_delinit(&buf->managed.list);
   2759         NineBuffer9_Upload(buf);
   2760     }
   2761 }
   2762 
   2763 static void
   2764 NineBeforeDraw( struct NineDevice9 *This )
   2765 {
   2766     /* Upload Managed dirty content */
   2767     validate_textures(This); /* may clobber state */
   2768     update_managed_buffers(This);
   2769 }
   2770 
   2771 static void
   2772 NineAfterDraw( struct NineDevice9 *This )
   2773 {
   2774     unsigned i;
   2775     struct nine_state *state = &This->state;
   2776     unsigned ps_mask = state->ps ? state->ps->rt_mask : 1;
   2777 
   2778     /* Flag render-targets with autogenmipmap for mipmap regeneration */
   2779     for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
   2780         struct NineSurface9 *rt = state->rt[i];
   2781 
   2782         if (rt && rt->desc.Format != D3DFMT_NULL && (ps_mask & (1 << i)) &&
   2783             rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP) {
   2784             assert(rt->texture == D3DRTYPE_TEXTURE ||
   2785                    rt->texture == D3DRTYPE_CUBETEXTURE);
   2786             NineBaseTexture9(rt->base.base.container)->dirty_mip = TRUE;
   2787         }
   2788     }
   2789 }
   2790 
   2791 HRESULT NINE_WINAPI
   2792 NineDevice9_DrawPrimitive( struct NineDevice9 *This,
   2793                            D3DPRIMITIVETYPE PrimitiveType,
   2794                            UINT StartVertex,
   2795                            UINT PrimitiveCount )
   2796 {
   2797     DBG("iface %p, PrimitiveType %u, StartVertex %u, PrimitiveCount %u\n",
   2798         This, PrimitiveType, StartVertex, PrimitiveCount);
   2799 
   2800     NineBeforeDraw(This);
   2801     nine_context_draw_primitive(This, PrimitiveType, StartVertex, PrimitiveCount);
   2802     NineAfterDraw(This);
   2803 
   2804     return D3D_OK;
   2805 }
   2806 
   2807 HRESULT NINE_WINAPI
   2808 NineDevice9_DrawIndexedPrimitive( struct NineDevice9 *This,
   2809                                   D3DPRIMITIVETYPE PrimitiveType,
   2810                                   INT BaseVertexIndex,
   2811                                   UINT MinVertexIndex,
   2812                                   UINT NumVertices,
   2813                                   UINT StartIndex,
   2814                                   UINT PrimitiveCount )
   2815 {
   2816     DBG("iface %p, PrimitiveType %u, BaseVertexIndex %u, MinVertexIndex %u "
   2817         "NumVertices %u, StartIndex %u, PrimitiveCount %u\n",
   2818         This, PrimitiveType, BaseVertexIndex, MinVertexIndex, NumVertices,
   2819         StartIndex, PrimitiveCount);
   2820 
   2821     user_assert(This->state.idxbuf, D3DERR_INVALIDCALL);
   2822     user_assert(This->state.vdecl, D3DERR_INVALIDCALL);
   2823 
   2824     NineBeforeDraw(This);
   2825     nine_context_draw_indexed_primitive(This, PrimitiveType, BaseVertexIndex,
   2826                                         MinVertexIndex, NumVertices, StartIndex,
   2827                                         PrimitiveCount);
   2828     NineAfterDraw(This);
   2829 
   2830     return D3D_OK;
   2831 }
   2832 
   2833 HRESULT NINE_WINAPI
   2834 NineDevice9_DrawPrimitiveUP( struct NineDevice9 *This,
   2835                              D3DPRIMITIVETYPE PrimitiveType,
   2836                              UINT PrimitiveCount,
   2837                              const void *pVertexStreamZeroData,
   2838                              UINT VertexStreamZeroStride )
   2839 {
   2840     struct pipe_vertex_buffer vtxbuf;
   2841 
   2842     DBG("iface %p, PrimitiveType %u, PrimitiveCount %u, data %p, stride %u\n",
   2843         This, PrimitiveType, PrimitiveCount,
   2844         pVertexStreamZeroData, VertexStreamZeroStride);
   2845 
   2846     user_assert(pVertexStreamZeroData && VertexStreamZeroStride,
   2847                 D3DERR_INVALIDCALL);
   2848     user_assert(PrimitiveCount, D3D_OK);
   2849 
   2850     vtxbuf.stride = VertexStreamZeroStride;
   2851     vtxbuf.buffer_offset = 0;
   2852     vtxbuf.buffer = NULL;
   2853     vtxbuf.user_buffer = pVertexStreamZeroData;
   2854 
   2855     if (!This->driver_caps.user_vbufs) {
   2856         u_upload_data(This->vertex_uploader,
   2857                       0,
   2858                       (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */
   2859                       4,
   2860                       vtxbuf.user_buffer,
   2861                       &vtxbuf.buffer_offset,
   2862                       &vtxbuf.buffer);
   2863         u_upload_unmap(This->vertex_uploader);
   2864         vtxbuf.user_buffer = NULL;
   2865     }
   2866 
   2867     NineBeforeDraw(This);
   2868     nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf);
   2869     NineAfterDraw(This);
   2870 
   2871     pipe_resource_reference(&vtxbuf.buffer, NULL);
   2872 
   2873     NineDevice9_PauseRecording(This);
   2874     NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
   2875     NineDevice9_ResumeRecording(This);
   2876 
   2877     return D3D_OK;
   2878 }
   2879 
   2880 HRESULT NINE_WINAPI
   2881 NineDevice9_DrawIndexedPrimitiveUP( struct NineDevice9 *This,
   2882                                     D3DPRIMITIVETYPE PrimitiveType,
   2883                                     UINT MinVertexIndex,
   2884                                     UINT NumVertices,
   2885                                     UINT PrimitiveCount,
   2886                                     const void *pIndexData,
   2887                                     D3DFORMAT IndexDataFormat,
   2888                                     const void *pVertexStreamZeroData,
   2889                                     UINT VertexStreamZeroStride )
   2890 {
   2891     struct pipe_vertex_buffer vbuf;
   2892     struct pipe_index_buffer ibuf;
   2893 
   2894     DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
   2895         "PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
   2896         "pVertexStreamZeroData %p, VertexStreamZeroStride %u\n",
   2897         This, PrimitiveType, MinVertexIndex, NumVertices, PrimitiveCount,
   2898         pIndexData, IndexDataFormat,
   2899         pVertexStreamZeroData, VertexStreamZeroStride);
   2900 
   2901     user_assert(pIndexData && pVertexStreamZeroData, D3DERR_INVALIDCALL);
   2902     user_assert(VertexStreamZeroStride, D3DERR_INVALIDCALL);
   2903     user_assert(IndexDataFormat == D3DFMT_INDEX16 ||
   2904                 IndexDataFormat == D3DFMT_INDEX32, D3DERR_INVALIDCALL);
   2905     user_assert(PrimitiveCount, D3D_OK);
   2906 
   2907     vbuf.stride = VertexStreamZeroStride;
   2908     vbuf.buffer_offset = 0;
   2909     vbuf.buffer = NULL;
   2910     vbuf.user_buffer = pVertexStreamZeroData;
   2911 
   2912     ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
   2913     ibuf.offset = 0;
   2914     ibuf.buffer = NULL;
   2915     ibuf.user_buffer = pIndexData;
   2916 
   2917     if (!This->driver_caps.user_vbufs) {
   2918         const unsigned base = MinVertexIndex * VertexStreamZeroStride;
   2919         u_upload_data(This->vertex_uploader,
   2920                       base,
   2921                       NumVertices * VertexStreamZeroStride, /* XXX */
   2922                       4,
   2923                       (const uint8_t *)vbuf.user_buffer + base,
   2924                       &vbuf.buffer_offset,
   2925                       &vbuf.buffer);
   2926         u_upload_unmap(This->vertex_uploader);
   2927         /* Won't be used: */
   2928         vbuf.buffer_offset -= base;
   2929         vbuf.user_buffer = NULL;
   2930     }
   2931     if (!This->driver_caps.user_ibufs) {
   2932         u_upload_data(This->index_uploader,
   2933                       0,
   2934                       (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * ibuf.index_size,
   2935                       4,
   2936                       ibuf.user_buffer,
   2937                       &ibuf.offset,
   2938                       &ibuf.buffer);
   2939         u_upload_unmap(This->index_uploader);
   2940         ibuf.user_buffer = NULL;
   2941     }
   2942 
   2943     NineBeforeDraw(This);
   2944     nine_context_draw_indexed_primitive_from_vtxbuf_idxbuf(This, PrimitiveType,
   2945                                                            MinVertexIndex,
   2946                                                            NumVertices,
   2947                                                            PrimitiveCount,
   2948                                                            &vbuf,
   2949                                                            &ibuf);
   2950     NineAfterDraw(This);
   2951 
   2952     pipe_resource_reference(&vbuf.buffer, NULL);
   2953     pipe_resource_reference(&ibuf.buffer, NULL);
   2954 
   2955     NineDevice9_PauseRecording(This);
   2956     NineDevice9_SetIndices(This, NULL);
   2957     NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
   2958     NineDevice9_ResumeRecording(This);
   2959 
   2960     return D3D_OK;
   2961 }
   2962 
   2963 HRESULT NINE_WINAPI
   2964 NineDevice9_ProcessVertices( struct NineDevice9 *This,
   2965                              UINT SrcStartIndex,
   2966                              UINT DestIndex,
   2967                              UINT VertexCount,
   2968                              IDirect3DVertexBuffer9 *pDestBuffer,
   2969                              IDirect3DVertexDeclaration9 *pVertexDecl,
   2970                              DWORD Flags )
   2971 {
   2972     struct pipe_screen *screen_sw = This->screen_sw;
   2973     struct pipe_context *pipe_sw = This->pipe_sw;
   2974     struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pVertexDecl);
   2975     struct NineVertexBuffer9 *dst = NineVertexBuffer9(pDestBuffer);
   2976     struct NineVertexShader9 *vs;
   2977     struct pipe_resource *resource;
   2978     struct pipe_transfer *transfer = NULL;
   2979     struct pipe_stream_output_info so;
   2980     struct pipe_stream_output_target *target;
   2981     struct pipe_draw_info draw;
   2982     struct pipe_box box;
   2983     bool programmable_vs = This->state.vs && !(This->state.vdecl && This->state.vdecl->position_t);
   2984     unsigned offsets[1] = {0};
   2985     HRESULT hr;
   2986     unsigned buffer_size;
   2987     void *map;
   2988 
   2989     DBG("This=%p SrcStartIndex=%u DestIndex=%u VertexCount=%u "
   2990         "pDestBuffer=%p pVertexDecl=%p Flags=%d\n",
   2991         This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer,
   2992         pVertexDecl, Flags);
   2993 
   2994     if (!screen_sw->get_param(screen_sw, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS)) {
   2995         DBG("ProcessVertices not supported\n");
   2996         return D3DERR_INVALIDCALL;
   2997     }
   2998 
   2999 
   3000     vs = programmable_vs ? This->state.vs : This->ff.vs;
   3001     /* Note: version is 0 for ff */
   3002     user_assert(vdecl || (vs->byte_code.version < 0x30 && dst->desc.FVF),
   3003                 D3DERR_INVALIDCALL);
   3004     if (!vdecl) {
   3005         DWORD FVF = dst->desc.FVF;
   3006         vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
   3007         if (!vdecl) {
   3008             hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
   3009             if (FAILED(hr))
   3010                 return hr;
   3011             vdecl->fvf = FVF;
   3012             util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
   3013             NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
   3014         }
   3015     }
   3016 
   3017     /* Flags: Can be 0 or D3DPV_DONOTCOPYDATA, and/or lock flags
   3018      * D3DPV_DONOTCOPYDATA -> Has effect only for ff. In particular
   3019      * if not set, everything from src will be used, and dst
   3020      * must match exactly the ff vs outputs.
   3021      * TODO: Handle all the checks, etc for ff */
   3022     user_assert(vdecl->position_t || programmable_vs,
   3023                 D3DERR_INVALIDCALL);
   3024 
   3025     /* TODO: Support vs < 3 and ff */
   3026     user_assert(vs->byte_code.version == 0x30,
   3027                 D3DERR_INVALIDCALL);
   3028     /* TODO: Not hardcode the constant buffers for swvp */
   3029     user_assert(This->may_swvp,
   3030                 D3DERR_INVALIDCALL);
   3031 
   3032     nine_state_prepare_draw_sw(This, vdecl, SrcStartIndex, VertexCount, &so);
   3033 
   3034     buffer_size = VertexCount * so.stride[0] * 4;
   3035     {
   3036         struct pipe_resource templ;
   3037 
   3038         memset(&templ, 0, sizeof(templ));
   3039         templ.target = PIPE_BUFFER;
   3040         templ.format = PIPE_FORMAT_R8_UNORM;
   3041         templ.width0 = buffer_size;
   3042         templ.flags = 0;
   3043         templ.bind = PIPE_BIND_STREAM_OUTPUT;
   3044         templ.usage = PIPE_USAGE_STREAM;
   3045         templ.height0 = templ.depth0 = templ.array_size = 1;
   3046         templ.last_level = templ.nr_samples = 0;
   3047 
   3048         resource = screen_sw->resource_create(screen_sw, &templ);
   3049         if (!resource)
   3050             return E_OUTOFMEMORY;
   3051     }
   3052     target = pipe_sw->create_stream_output_target(pipe_sw, resource,
   3053                                                   0, buffer_size);
   3054     if (!target) {
   3055         pipe_resource_reference(&resource, NULL);
   3056         return D3DERR_DRIVERINTERNALERROR;
   3057     }
   3058 
   3059     draw.mode = PIPE_PRIM_POINTS;
   3060     draw.count = VertexCount;
   3061     draw.start_instance = 0;
   3062     draw.primitive_restart = FALSE;
   3063     draw.restart_index = 0;
   3064     draw.count_from_stream_output = NULL;
   3065     draw.indirect = NULL;
   3066     draw.indirect_params = NULL;
   3067     draw.instance_count = 1;
   3068     draw.indexed = FALSE;
   3069     draw.start = 0;
   3070     draw.index_bias = 0;
   3071     draw.min_index = 0;
   3072     draw.max_index = VertexCount - 1;
   3073 
   3074 
   3075     pipe_sw->set_stream_output_targets(pipe_sw, 1, &target, offsets);
   3076 
   3077     pipe_sw->draw_vbo(pipe_sw, &draw);
   3078 
   3079     pipe_sw->set_stream_output_targets(pipe_sw, 0, NULL, 0);
   3080     pipe_sw->stream_output_target_destroy(pipe_sw, target);
   3081 
   3082     u_box_1d(0, VertexCount * so.stride[0] * 4, &box);
   3083     map = pipe_sw->transfer_map(pipe_sw, resource, 0, PIPE_TRANSFER_READ, &box,
   3084                                 &transfer);
   3085     if (!map) {
   3086         hr = D3DERR_DRIVERINTERNALERROR;
   3087         goto out;
   3088     }
   3089 
   3090     hr = NineVertexDeclaration9_ConvertStreamOutput(vdecl,
   3091                                                     dst, DestIndex, VertexCount,
   3092                                                     map, &so);
   3093     if (transfer)
   3094         pipe_sw->transfer_unmap(pipe_sw, transfer);
   3095 
   3096 out:
   3097     nine_state_after_draw_sw(This);
   3098     pipe_resource_reference(&resource, NULL);
   3099     return hr;
   3100 }
   3101 
   3102 HRESULT NINE_WINAPI
   3103 NineDevice9_CreateVertexDeclaration( struct NineDevice9 *This,
   3104                                      const D3DVERTEXELEMENT9 *pVertexElements,
   3105                                      IDirect3DVertexDeclaration9 **ppDecl )
   3106 {
   3107     struct NineVertexDeclaration9 *vdecl;
   3108 
   3109     DBG("This=%p pVertexElements=%p ppDecl=%p\n",
   3110         This, pVertexElements, ppDecl);
   3111 
   3112     HRESULT hr = NineVertexDeclaration9_new(This, pVertexElements, &vdecl);
   3113     if (SUCCEEDED(hr))
   3114         *ppDecl = (IDirect3DVertexDeclaration9 *)vdecl;
   3115 
   3116     return hr;
   3117 }
   3118 
   3119 HRESULT NINE_WINAPI
   3120 NineDevice9_SetVertexDeclaration( struct NineDevice9 *This,
   3121                                   IDirect3DVertexDeclaration9 *pDecl )
   3122 {
   3123     struct nine_state *state = This->update;
   3124     struct NineVertexDeclaration9 *vdecl = NineVertexDeclaration9(pDecl);
   3125 
   3126     DBG("This=%p pDecl=%p\n", This, pDecl);
   3127 
   3128     if (unlikely(This->is_recording)) {
   3129         nine_bind(&state->vdecl, vdecl);
   3130         state->changed.group |= NINE_STATE_VDECL;
   3131         return D3D_OK;
   3132     }
   3133 
   3134     if (state->vdecl == vdecl)
   3135         return D3D_OK;
   3136 
   3137     nine_bind(&state->vdecl, vdecl);
   3138 
   3139     nine_context_set_vertex_declaration(This, vdecl);
   3140 
   3141     return D3D_OK;
   3142 }
   3143 
   3144 HRESULT NINE_WINAPI
   3145 NineDevice9_GetVertexDeclaration( struct NineDevice9 *This,
   3146                                   IDirect3DVertexDeclaration9 **ppDecl )
   3147 {
   3148     user_assert(ppDecl, D3DERR_INVALIDCALL);
   3149 
   3150     *ppDecl = (IDirect3DVertexDeclaration9 *)This->state.vdecl;
   3151     if (*ppDecl)
   3152         NineUnknown_AddRef(NineUnknown(*ppDecl));
   3153     return D3D_OK;
   3154 }
   3155 
   3156 HRESULT NINE_WINAPI
   3157 NineDevice9_SetFVF( struct NineDevice9 *This,
   3158                     DWORD FVF )
   3159 {
   3160     struct NineVertexDeclaration9 *vdecl;
   3161     HRESULT hr;
   3162 
   3163     DBG("FVF = %08x\n", FVF);
   3164     if (!FVF)
   3165         return D3D_OK; /* like wine */
   3166 
   3167     vdecl = util_hash_table_get(This->ff.ht_fvf, &FVF);
   3168     if (!vdecl) {
   3169         hr = NineVertexDeclaration9_new_from_fvf(This, FVF, &vdecl);
   3170         if (FAILED(hr))
   3171             return hr;
   3172         vdecl->fvf = FVF;
   3173         util_hash_table_set(This->ff.ht_fvf, &vdecl->fvf, vdecl);
   3174         NineUnknown_ConvertRefToBind(NineUnknown(vdecl));
   3175     }
   3176     return NineDevice9_SetVertexDeclaration(
   3177         This, (IDirect3DVertexDeclaration9 *)vdecl);
   3178 }
   3179 
   3180 HRESULT NINE_WINAPI
   3181 NineDevice9_GetFVF( struct NineDevice9 *This,
   3182                     DWORD *pFVF )
   3183 {
   3184     *pFVF = This->state.vdecl ? This->state.vdecl->fvf : 0;
   3185     return D3D_OK;
   3186 }
   3187 
   3188 HRESULT NINE_WINAPI
   3189 NineDevice9_CreateVertexShader( struct NineDevice9 *This,
   3190                                 const DWORD *pFunction,
   3191                                 IDirect3DVertexShader9 **ppShader )
   3192 {
   3193     struct NineVertexShader9 *vs;
   3194     HRESULT hr;
   3195 
   3196     DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);
   3197 
   3198     hr = NineVertexShader9_new(This, &vs, pFunction, NULL);
   3199     if (FAILED(hr))
   3200         return hr;
   3201     *ppShader = (IDirect3DVertexShader9 *)vs;
   3202     return D3D_OK;
   3203 }
   3204 
   3205 HRESULT NINE_WINAPI
   3206 NineDevice9_SetVertexShader( struct NineDevice9 *This,
   3207                              IDirect3DVertexShader9 *pShader )
   3208 {
   3209     struct nine_state *state = This->update;
   3210     struct NineVertexShader9 *vs_shader = (struct NineVertexShader9*)pShader;
   3211 
   3212     DBG("This=%p pShader=%p\n", This, pShader);
   3213 
   3214     if (unlikely(This->is_recording)) {
   3215         nine_bind(&state->vs, vs_shader);
   3216         state->changed.group |= NINE_STATE_VS;
   3217         return D3D_OK;
   3218     }
   3219 
   3220     if (state->vs == vs_shader)
   3221       return D3D_OK;
   3222 
   3223     nine_bind(&state->vs, vs_shader);
   3224 
   3225     nine_context_set_vertex_shader(This, vs_shader);
   3226 
   3227     return D3D_OK;
   3228 }
   3229 
   3230 HRESULT NINE_WINAPI
   3231 NineDevice9_GetVertexShader( struct NineDevice9 *This,
   3232                              IDirect3DVertexShader9 **ppShader )
   3233 {
   3234     user_assert(ppShader, D3DERR_INVALIDCALL);
   3235     nine_reference_set(ppShader, This->state.vs);
   3236     return D3D_OK;
   3237 }
   3238 
   3239 HRESULT NINE_WINAPI
   3240 NineDevice9_SetVertexShaderConstantF( struct NineDevice9 *This,
   3241                                       UINT StartRegister,
   3242                                       const float *pConstantData,
   3243                                       UINT Vector4fCount )
   3244 {
   3245     struct nine_state *state = This->update;
   3246     float *vs_const_f = state->vs_const_f;
   3247 
   3248     DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
   3249         This, StartRegister, pConstantData, Vector4fCount);
   3250 
   3251     user_assert(StartRegister                  < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
   3252     user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
   3253 
   3254     if (!Vector4fCount)
   3255        return D3D_OK;
   3256     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3257 
   3258     if (unlikely(This->is_recording)) {
   3259         memcpy(&vs_const_f[StartRegister * 4],
   3260                pConstantData,
   3261                Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
   3262 
   3263         nine_ranges_insert(&state->changed.vs_const_f,
   3264                            StartRegister, StartRegister + Vector4fCount,
   3265                            &This->range_pool);
   3266 
   3267         state->changed.group |= NINE_STATE_VS_CONST;
   3268 
   3269         return D3D_OK;
   3270     }
   3271 
   3272     if (!memcmp(&vs_const_f[StartRegister * 4], pConstantData,
   3273                 Vector4fCount * 4 * sizeof(state->vs_const_f[0])))
   3274         return D3D_OK;
   3275 
   3276     memcpy(&vs_const_f[StartRegister * 4],
   3277            pConstantData,
   3278            Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
   3279 
   3280     nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData,
   3281                                               Vector4fCount * 4 * sizeof(state->vs_const_f[0]),
   3282                                               Vector4fCount);
   3283 
   3284     return D3D_OK;
   3285 }
   3286 
   3287 HRESULT NINE_WINAPI
   3288 NineDevice9_GetVertexShaderConstantF( struct NineDevice9 *This,
   3289                                       UINT StartRegister,
   3290                                       float *pConstantData,
   3291                                       UINT Vector4fCount )
   3292 {
   3293     const struct nine_state *state = &This->state;
   3294 
   3295     user_assert(StartRegister                  < This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
   3296     user_assert(StartRegister + Vector4fCount <= This->caps.MaxVertexShaderConst, D3DERR_INVALIDCALL);
   3297     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3298 
   3299     memcpy(pConstantData,
   3300            &state->vs_const_f[StartRegister * 4],
   3301            Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
   3302 
   3303     return D3D_OK;
   3304 }
   3305 
   3306 HRESULT NINE_WINAPI
   3307 NineDevice9_SetVertexShaderConstantI( struct NineDevice9 *This,
   3308                                       UINT StartRegister,
   3309                                       const int *pConstantData,
   3310                                       UINT Vector4iCount )
   3311 {
   3312     struct nine_state *state = This->update;
   3313     int i;
   3314 
   3315     DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
   3316         This, StartRegister, pConstantData, Vector4iCount);
   3317 
   3318     user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),
   3319                 D3DERR_INVALIDCALL);
   3320     user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),
   3321                 D3DERR_INVALIDCALL);
   3322     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3323 
   3324     if (This->driver_caps.vs_integer) {
   3325         if (!This->is_recording) {
   3326             if (!memcmp(&state->vs_const_i[4 * StartRegister], pConstantData,
   3327                         Vector4iCount * sizeof(int[4])))
   3328                 return D3D_OK;
   3329         }
   3330         memcpy(&state->vs_const_i[4 * StartRegister],
   3331                pConstantData,
   3332                Vector4iCount * sizeof(int[4]));
   3333     } else {
   3334         for (i = 0; i < Vector4iCount; i++) {
   3335             state->vs_const_i[4 * (StartRegister + i)] = fui((float)(pConstantData[4 * i]));
   3336             state->vs_const_i[4 * (StartRegister + i) + 1] = fui((float)(pConstantData[4 * i + 1]));
   3337             state->vs_const_i[4 * (StartRegister + i) + 2] = fui((float)(pConstantData[4 * i + 2]));
   3338             state->vs_const_i[4 * (StartRegister + i) + 3] = fui((float)(pConstantData[4 * i + 3]));
   3339         }
   3340     }
   3341 
   3342     if (unlikely(This->is_recording)) {
   3343         nine_ranges_insert(&state->changed.vs_const_i,
   3344                            StartRegister, StartRegister + Vector4iCount,
   3345                            &This->range_pool);
   3346         state->changed.group |= NINE_STATE_VS_CONST;
   3347     } else
   3348         nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData,
   3349                                                   Vector4iCount * sizeof(int[4]), Vector4iCount);
   3350 
   3351     return D3D_OK;
   3352 }
   3353 
   3354 HRESULT NINE_WINAPI
   3355 NineDevice9_GetVertexShaderConstantI( struct NineDevice9 *This,
   3356                                       UINT StartRegister,
   3357                                       int *pConstantData,
   3358                                       UINT Vector4iCount )
   3359 {
   3360     const struct nine_state *state = &This->state;
   3361     int i;
   3362 
   3363     user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),
   3364                 D3DERR_INVALIDCALL);
   3365     user_assert(StartRegister + Vector4iCount <= (This->may_swvp ? NINE_MAX_CONST_I_SWVP : NINE_MAX_CONST_I),
   3366                 D3DERR_INVALIDCALL);
   3367     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3368 
   3369     if (This->driver_caps.vs_integer) {
   3370         memcpy(pConstantData,
   3371                &state->vs_const_i[4 * StartRegister],
   3372                Vector4iCount * sizeof(int[4]));
   3373     } else {
   3374         for (i = 0; i < Vector4iCount; i++) {
   3375             pConstantData[4 * i] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i)]);
   3376             pConstantData[4 * i + 1] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 1]);
   3377             pConstantData[4 * i + 2] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 2]);
   3378             pConstantData[4 * i + 3] = (int32_t) uif(state->vs_const_i[4 * (StartRegister + i) + 3]);
   3379         }
   3380     }
   3381 
   3382     return D3D_OK;
   3383 }
   3384 
   3385 HRESULT NINE_WINAPI
   3386 NineDevice9_SetVertexShaderConstantB( struct NineDevice9 *This,
   3387                                       UINT StartRegister,
   3388                                       const BOOL *pConstantData,
   3389                                       UINT BoolCount )
   3390 {
   3391     struct nine_state *state = This->update;
   3392     int i;
   3393     uint32_t bool_true = This->driver_caps.vs_integer ? 0xFFFFFFFF : fui(1.0f);
   3394 
   3395     DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
   3396         This, StartRegister, pConstantData, BoolCount);
   3397 
   3398     user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),
   3399                 D3DERR_INVALIDCALL);
   3400     user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),
   3401                 D3DERR_INVALIDCALL);
   3402     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3403 
   3404     if (!This->is_recording) {
   3405         bool noChange = true;
   3406         for (i = 0; i < BoolCount; i++) {
   3407             if (!!state->vs_const_b[StartRegister + i] != !!pConstantData[i])
   3408               noChange = false;
   3409         }
   3410         if (noChange)
   3411             return D3D_OK;
   3412     }
   3413 
   3414     for (i = 0; i < BoolCount; i++)
   3415         state->vs_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
   3416 
   3417     if (unlikely(This->is_recording)) {
   3418         nine_ranges_insert(&state->changed.vs_const_b,
   3419                            StartRegister, StartRegister + BoolCount,
   3420                            &This->range_pool);
   3421         state->changed.group |= NINE_STATE_VS_CONST;
   3422     } else
   3423         nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData,
   3424                                                   sizeof(BOOL) * BoolCount, BoolCount);
   3425 
   3426     return D3D_OK;
   3427 }
   3428 
   3429 HRESULT NINE_WINAPI
   3430 NineDevice9_GetVertexShaderConstantB( struct NineDevice9 *This,
   3431                                       UINT StartRegister,
   3432                                       BOOL *pConstantData,
   3433                                       UINT BoolCount )
   3434 {
   3435     const struct nine_state *state = &This->state;
   3436     int i;
   3437 
   3438     user_assert(StartRegister < (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),
   3439                 D3DERR_INVALIDCALL);
   3440     user_assert(StartRegister + BoolCount <= (This->may_swvp ? NINE_MAX_CONST_B_SWVP : NINE_MAX_CONST_B),
   3441                 D3DERR_INVALIDCALL);
   3442     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3443 
   3444     for (i = 0; i < BoolCount; i++)
   3445         pConstantData[i] = state->vs_const_b[StartRegister + i] != 0 ? TRUE : FALSE;
   3446 
   3447     return D3D_OK;
   3448 }
   3449 
   3450 HRESULT NINE_WINAPI
   3451 NineDevice9_SetStreamSource( struct NineDevice9 *This,
   3452                              UINT StreamNumber,
   3453                              IDirect3DVertexBuffer9 *pStreamData,
   3454                              UINT OffsetInBytes,
   3455                              UINT Stride )
   3456 {
   3457     struct nine_state *state = This->update;
   3458     struct NineVertexBuffer9 *pVBuf9 = NineVertexBuffer9(pStreamData);
   3459     const unsigned i = StreamNumber;
   3460 
   3461     DBG("This=%p StreamNumber=%u pStreamData=%p OffsetInBytes=%u Stride=%u\n",
   3462         This, StreamNumber, pStreamData, OffsetInBytes, Stride);
   3463 
   3464     user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
   3465     user_assert(Stride <= This->caps.MaxStreamStride, D3DERR_INVALIDCALL);
   3466 
   3467     if (unlikely(This->is_recording)) {
   3468         nine_bind(&state->stream[i], pStreamData);
   3469         state->changed.vtxbuf |= 1 << StreamNumber;
   3470         state->vtxbuf[i].stride = Stride;
   3471         state->vtxbuf[i].buffer_offset = OffsetInBytes;
   3472         return D3D_OK;
   3473     }
   3474 
   3475     if (state->stream[i] == NineVertexBuffer9(pStreamData) &&
   3476         state->vtxbuf[i].stride == Stride &&
   3477         state->vtxbuf[i].buffer_offset == OffsetInBytes)
   3478         return D3D_OK;
   3479 
   3480     state->vtxbuf[i].stride = Stride;
   3481     state->vtxbuf[i].buffer_offset = OffsetInBytes;
   3482 
   3483     NineBindBufferToDevice(This,
   3484                            (struct NineBuffer9 **)&state->stream[i],
   3485                            (struct NineBuffer9 *)pVBuf9);
   3486 
   3487     nine_context_set_stream_source(This,
   3488                                    StreamNumber,
   3489                                    pVBuf9,
   3490                                    OffsetInBytes,
   3491                                    Stride);
   3492 
   3493     return D3D_OK;
   3494 }
   3495 
   3496 HRESULT NINE_WINAPI
   3497 NineDevice9_GetStreamSource( struct NineDevice9 *This,
   3498                              UINT StreamNumber,
   3499                              IDirect3DVertexBuffer9 **ppStreamData,
   3500                              UINT *pOffsetInBytes,
   3501                              UINT *pStride )
   3502 {
   3503     const struct nine_state *state = &This->state;
   3504     const unsigned i = StreamNumber;
   3505 
   3506     user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
   3507     user_assert(ppStreamData, D3DERR_INVALIDCALL);
   3508 
   3509     nine_reference_set(ppStreamData, state->stream[i]);
   3510     *pStride = state->vtxbuf[i].stride;
   3511     *pOffsetInBytes = state->vtxbuf[i].buffer_offset;
   3512 
   3513     return D3D_OK;
   3514 }
   3515 
   3516 HRESULT NINE_WINAPI
   3517 NineDevice9_SetStreamSourceFreq( struct NineDevice9 *This,
   3518                                  UINT StreamNumber,
   3519                                  UINT Setting )
   3520 {
   3521     struct nine_state *state = This->update;
   3522     /* const UINT freq = Setting & 0x7FFFFF; */
   3523 
   3524     DBG("This=%p StreamNumber=%u FrequencyParameter=0x%x\n", This,
   3525         StreamNumber, Setting);
   3526 
   3527     user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
   3528     user_assert(StreamNumber != 0 || !(Setting & D3DSTREAMSOURCE_INSTANCEDATA),
   3529                 D3DERR_INVALIDCALL);
   3530     user_assert(!((Setting & D3DSTREAMSOURCE_INSTANCEDATA) &&
   3531                   (Setting & D3DSTREAMSOURCE_INDEXEDDATA)), D3DERR_INVALIDCALL);
   3532     user_assert(Setting, D3DERR_INVALIDCALL);
   3533 
   3534     if (unlikely(This->is_recording)) {
   3535         state->stream_freq[StreamNumber] = Setting;
   3536         state->changed.stream_freq |= 1 << StreamNumber;
   3537         if (StreamNumber != 0)
   3538             state->changed.group |= NINE_STATE_STREAMFREQ;
   3539         return D3D_OK;
   3540     }
   3541 
   3542     if (state->stream_freq[StreamNumber] == Setting)
   3543         return D3D_OK;
   3544 
   3545     state->stream_freq[StreamNumber] = Setting;
   3546 
   3547     nine_context_set_stream_source_freq(This, StreamNumber, Setting);
   3548     return D3D_OK;
   3549 }
   3550 
   3551 HRESULT NINE_WINAPI
   3552 NineDevice9_GetStreamSourceFreq( struct NineDevice9 *This,
   3553                                  UINT StreamNumber,
   3554                                  UINT *pSetting )
   3555 {
   3556     user_assert(StreamNumber < This->caps.MaxStreams, D3DERR_INVALIDCALL);
   3557     *pSetting = This->state.stream_freq[StreamNumber];
   3558     return D3D_OK;
   3559 }
   3560 
   3561 HRESULT NINE_WINAPI
   3562 NineDevice9_SetIndices( struct NineDevice9 *This,
   3563                         IDirect3DIndexBuffer9 *pIndexData )
   3564 {
   3565     struct nine_state *state = This->update;
   3566     struct NineIndexBuffer9 *idxbuf = NineIndexBuffer9(pIndexData);
   3567 
   3568     DBG("This=%p pIndexData=%p\n", This, pIndexData);
   3569 
   3570     if (unlikely(This->is_recording)) {
   3571         nine_bind(&state->idxbuf, idxbuf);
   3572         state->changed.group |= NINE_STATE_IDXBUF;
   3573         return D3D_OK;
   3574     }
   3575 
   3576     if (state->idxbuf == idxbuf)
   3577         return D3D_OK;
   3578 
   3579     NineBindBufferToDevice(This,
   3580                            (struct NineBuffer9 **)&state->idxbuf,
   3581                            (struct NineBuffer9 *)idxbuf);
   3582 
   3583     nine_context_set_indices(This, idxbuf);
   3584 
   3585     return D3D_OK;
   3586 }
   3587 
   3588 /* XXX: wine/d3d9 doesn't have pBaseVertexIndex, and it doesn't make sense
   3589  * here because it's an argument passed to the Draw calls.
   3590  */
   3591 HRESULT NINE_WINAPI
   3592 NineDevice9_GetIndices( struct NineDevice9 *This,
   3593                         IDirect3DIndexBuffer9 **ppIndexData)
   3594 {
   3595     user_assert(ppIndexData, D3DERR_INVALIDCALL);
   3596     nine_reference_set(ppIndexData, This->state.idxbuf);
   3597     return D3D_OK;
   3598 }
   3599 
   3600 HRESULT NINE_WINAPI
   3601 NineDevice9_CreatePixelShader( struct NineDevice9 *This,
   3602                                const DWORD *pFunction,
   3603                                IDirect3DPixelShader9 **ppShader )
   3604 {
   3605     struct NinePixelShader9 *ps;
   3606     HRESULT hr;
   3607 
   3608     DBG("This=%p pFunction=%p ppShader=%p\n", This, pFunction, ppShader);
   3609 
   3610     hr = NinePixelShader9_new(This, &ps, pFunction, NULL);
   3611     if (FAILED(hr))
   3612         return hr;
   3613     *ppShader = (IDirect3DPixelShader9 *)ps;
   3614     return D3D_OK;
   3615 }
   3616 
   3617 HRESULT NINE_WINAPI
   3618 NineDevice9_SetPixelShader( struct NineDevice9 *This,
   3619                             IDirect3DPixelShader9 *pShader )
   3620 {
   3621     struct nine_state *state = This->update;
   3622     struct NinePixelShader9 *ps = (struct NinePixelShader9*)pShader;
   3623 
   3624     DBG("This=%p pShader=%p\n", This, pShader);
   3625 
   3626     if (unlikely(This->is_recording)) {
   3627         /* Technically we need NINE_STATE_FB only
   3628          * if the ps mask changes, but put it always
   3629          * to be safe */
   3630         nine_bind(&state->ps, pShader);
   3631         state->changed.group |= NINE_STATE_PS | NINE_STATE_FB;
   3632         return D3D_OK;
   3633     }
   3634 
   3635     if (state->ps == ps)
   3636         return D3D_OK;
   3637 
   3638     nine_bind(&state->ps, ps);
   3639 
   3640     nine_context_set_pixel_shader(This, ps);
   3641 
   3642     return D3D_OK;
   3643 }
   3644 
   3645 HRESULT NINE_WINAPI
   3646 NineDevice9_GetPixelShader( struct NineDevice9 *This,
   3647                             IDirect3DPixelShader9 **ppShader )
   3648 {
   3649     user_assert(ppShader, D3DERR_INVALIDCALL);
   3650     nine_reference_set(ppShader, This->state.ps);
   3651     return D3D_OK;
   3652 }
   3653 
   3654 HRESULT NINE_WINAPI
   3655 NineDevice9_SetPixelShaderConstantF( struct NineDevice9 *This,
   3656                                      UINT StartRegister,
   3657                                      const float *pConstantData,
   3658                                      UINT Vector4fCount )
   3659 {
   3660     struct nine_state *state = This->update;
   3661 
   3662     DBG("This=%p StartRegister=%u pConstantData=%p Vector4fCount=%u\n",
   3663         This, StartRegister, pConstantData, Vector4fCount);
   3664 
   3665     user_assert(StartRegister                  < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
   3666     user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
   3667 
   3668     if (!Vector4fCount)
   3669        return D3D_OK;
   3670     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3671 
   3672     if (unlikely(This->is_recording)) {
   3673         memcpy(&state->ps_const_f[StartRegister * 4],
   3674                pConstantData,
   3675                Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
   3676 
   3677         nine_ranges_insert(&state->changed.ps_const_f,
   3678                            StartRegister, StartRegister + Vector4fCount,
   3679                            &This->range_pool);
   3680 
   3681         state->changed.group |= NINE_STATE_PS_CONST;
   3682         return D3D_OK;
   3683     }
   3684 
   3685     if (!memcmp(&state->ps_const_f[StartRegister * 4], pConstantData,
   3686                 Vector4fCount * 4 * sizeof(state->ps_const_f[0])))
   3687         return D3D_OK;
   3688 
   3689     memcpy(&state->ps_const_f[StartRegister * 4],
   3690            pConstantData,
   3691            Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
   3692 
   3693     nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData,
   3694                                              Vector4fCount * 4 * sizeof(state->ps_const_f[0]),
   3695                                              Vector4fCount);
   3696 
   3697     return D3D_OK;
   3698 }
   3699 
   3700 HRESULT NINE_WINAPI
   3701 NineDevice9_GetPixelShaderConstantF( struct NineDevice9 *This,
   3702                                      UINT StartRegister,
   3703                                      float *pConstantData,
   3704                                      UINT Vector4fCount )
   3705 {
   3706     const struct nine_state *state = &This->state;
   3707 
   3708     user_assert(StartRegister                  < NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
   3709     user_assert(StartRegister + Vector4fCount <= NINE_MAX_CONST_F_PS3, D3DERR_INVALIDCALL);
   3710     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3711 
   3712     memcpy(pConstantData,
   3713            &state->ps_const_f[StartRegister * 4],
   3714            Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
   3715 
   3716     return D3D_OK;
   3717 }
   3718 
   3719 HRESULT NINE_WINAPI
   3720 NineDevice9_SetPixelShaderConstantI( struct NineDevice9 *This,
   3721                                      UINT StartRegister,
   3722                                      const int *pConstantData,
   3723                                      UINT Vector4iCount )
   3724 {
   3725     struct nine_state *state = This->update;
   3726     int i;
   3727 
   3728     DBG("This=%p StartRegister=%u pConstantData=%p Vector4iCount=%u\n",
   3729         This, StartRegister, pConstantData, Vector4iCount);
   3730 
   3731     user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
   3732     user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
   3733     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3734 
   3735     if (This->driver_caps.ps_integer) {
   3736         if (!This->is_recording) {
   3737             if (!memcmp(&state->ps_const_i[StartRegister][0], pConstantData,
   3738                         Vector4iCount * sizeof(state->ps_const_i[0])))
   3739                 return D3D_OK;
   3740         }
   3741         memcpy(&state->ps_const_i[StartRegister][0],
   3742                pConstantData,
   3743                Vector4iCount * sizeof(state->ps_const_i[0]));
   3744     } else {
   3745         for (i = 0; i < Vector4iCount; i++) {
   3746             state->ps_const_i[StartRegister+i][0] = fui((float)(pConstantData[4*i]));
   3747             state->ps_const_i[StartRegister+i][1] = fui((float)(pConstantData[4*i+1]));
   3748             state->ps_const_i[StartRegister+i][2] = fui((float)(pConstantData[4*i+2]));
   3749             state->ps_const_i[StartRegister+i][3] = fui((float)(pConstantData[4*i+3]));
   3750         }
   3751     }
   3752 
   3753     if (unlikely(This->is_recording)) {
   3754         state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
   3755         state->changed.group |= NINE_STATE_PS_CONST;
   3756     } else
   3757         nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData,
   3758                                                  sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount);
   3759 
   3760     return D3D_OK;
   3761 }
   3762 
   3763 HRESULT NINE_WINAPI
   3764 NineDevice9_GetPixelShaderConstantI( struct NineDevice9 *This,
   3765                                      UINT StartRegister,
   3766                                      int *pConstantData,
   3767                                      UINT Vector4iCount )
   3768 {
   3769     const struct nine_state *state = &This->state;
   3770     int i;
   3771 
   3772     user_assert(StartRegister                  < NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
   3773     user_assert(StartRegister + Vector4iCount <= NINE_MAX_CONST_I, D3DERR_INVALIDCALL);
   3774     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3775 
   3776     if (This->driver_caps.ps_integer) {
   3777         memcpy(pConstantData,
   3778                &state->ps_const_i[StartRegister][0],
   3779                Vector4iCount * sizeof(state->ps_const_i[0]));
   3780     } else {
   3781         for (i = 0; i < Vector4iCount; i++) {
   3782             pConstantData[4*i] = (int32_t) uif(state->ps_const_i[StartRegister+i][0]);
   3783             pConstantData[4*i+1] = (int32_t) uif(state->ps_const_i[StartRegister+i][1]);
   3784             pConstantData[4*i+2] = (int32_t) uif(state->ps_const_i[StartRegister+i][2]);
   3785             pConstantData[4*i+3] = (int32_t) uif(state->ps_const_i[StartRegister+i][3]);
   3786         }
   3787     }
   3788 
   3789     return D3D_OK;
   3790 }
   3791 
   3792 HRESULT NINE_WINAPI
   3793 NineDevice9_SetPixelShaderConstantB( struct NineDevice9 *This,
   3794                                      UINT StartRegister,
   3795                                      const BOOL *pConstantData,
   3796                                      UINT BoolCount )
   3797 {
   3798     struct nine_state *state = This->update;
   3799     int i;
   3800     uint32_t bool_true = This->driver_caps.ps_integer ? 0xFFFFFFFF : fui(1.0f);
   3801 
   3802     DBG("This=%p StartRegister=%u pConstantData=%p BoolCount=%u\n",
   3803         This, StartRegister, pConstantData, BoolCount);
   3804 
   3805     user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
   3806     user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
   3807     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3808 
   3809     if (!This->is_recording) {
   3810         bool noChange = true;
   3811         for (i = 0; i < BoolCount; i++) {
   3812             if (!!state->ps_const_b[StartRegister + i] != !!pConstantData[i])
   3813               noChange = false;
   3814         }
   3815         if (noChange)
   3816             return D3D_OK;
   3817     }
   3818 
   3819     for (i = 0; i < BoolCount; i++)
   3820         state->ps_const_b[StartRegister + i] = pConstantData[i] ? bool_true : 0;
   3821 
   3822     if (unlikely(This->is_recording)) {
   3823         state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;
   3824         state->changed.group |= NINE_STATE_PS_CONST;
   3825     } else
   3826         nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData,
   3827                                                  sizeof(BOOL) * BoolCount, BoolCount);
   3828 
   3829     return D3D_OK;
   3830 }
   3831 
   3832 HRESULT NINE_WINAPI
   3833 NineDevice9_GetPixelShaderConstantB( struct NineDevice9 *This,
   3834                                      UINT StartRegister,
   3835                                      BOOL *pConstantData,
   3836                                      UINT BoolCount )
   3837 {
   3838     const struct nine_state *state = &This->state;
   3839     int i;
   3840 
   3841     user_assert(StartRegister              < NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
   3842     user_assert(StartRegister + BoolCount <= NINE_MAX_CONST_B, D3DERR_INVALIDCALL);
   3843     user_assert(pConstantData, D3DERR_INVALIDCALL);
   3844 
   3845     for (i = 0; i < BoolCount; i++)
   3846         pConstantData[i] = state->ps_const_b[StartRegister + i] ? TRUE : FALSE;
   3847 
   3848     return D3D_OK;
   3849 }
   3850 
   3851 HRESULT NINE_WINAPI
   3852 NineDevice9_DrawRectPatch( struct NineDevice9 *This,
   3853                            UINT Handle,
   3854                            const float *pNumSegs,
   3855                            const D3DRECTPATCH_INFO *pRectPatchInfo )
   3856 {
   3857     STUB(D3DERR_INVALIDCALL);
   3858 }
   3859 
   3860 HRESULT NINE_WINAPI
   3861 NineDevice9_DrawTriPatch( struct NineDevice9 *This,
   3862                           UINT Handle,
   3863                           const float *pNumSegs,
   3864                           const D3DTRIPATCH_INFO *pTriPatchInfo )
   3865 {
   3866     STUB(D3DERR_INVALIDCALL);
   3867 }
   3868 
   3869 HRESULT NINE_WINAPI
   3870 NineDevice9_DeletePatch( struct NineDevice9 *This,
   3871                          UINT Handle )
   3872 {
   3873     STUB(D3DERR_INVALIDCALL);
   3874 }
   3875 
   3876 HRESULT NINE_WINAPI
   3877 NineDevice9_CreateQuery( struct NineDevice9 *This,
   3878                          D3DQUERYTYPE Type,
   3879                          IDirect3DQuery9 **ppQuery )
   3880 {
   3881     struct NineQuery9 *query;
   3882     HRESULT hr;
   3883 
   3884     DBG("This=%p Type=%d ppQuery=%p\n", This, Type, ppQuery);
   3885 
   3886     hr = nine_is_query_supported(This->screen, Type);
   3887     if (!ppQuery || hr != D3D_OK)
   3888         return hr;
   3889 
   3890     hr = NineQuery9_new(This, &query, Type);
   3891     if (FAILED(hr))
   3892         return hr;
   3893     *ppQuery = (IDirect3DQuery9 *)query;
   3894     return D3D_OK;
   3895 }
   3896 
   3897 IDirect3DDevice9Vtbl NineDevice9_vtable = {
   3898     (void *)NineUnknown_QueryInterface,
   3899     (void *)NineUnknown_AddRef,
   3900     (void *)NineUnknown_Release,
   3901     (void *)NineDevice9_TestCooperativeLevel,
   3902     (void *)NineDevice9_GetAvailableTextureMem,
   3903     (void *)NineDevice9_EvictManagedResources,
   3904     (void *)NineDevice9_GetDirect3D,
   3905     (void *)NineDevice9_GetDeviceCaps,
   3906     (void *)NineDevice9_GetDisplayMode,
   3907     (void *)NineDevice9_GetCreationParameters,
   3908     (void *)NineDevice9_SetCursorProperties,
   3909     (void *)NineDevice9_SetCursorPosition,
   3910     (void *)NineDevice9_ShowCursor,
   3911     (void *)NineDevice9_CreateAdditionalSwapChain,
   3912     (void *)NineDevice9_GetSwapChain,
   3913     (void *)NineDevice9_GetNumberOfSwapChains,
   3914     (void *)NineDevice9_Reset,
   3915     (void *)NineDevice9_Present,
   3916     (void *)NineDevice9_GetBackBuffer,
   3917     (void *)NineDevice9_GetRasterStatus,
   3918     (void *)NineDevice9_SetDialogBoxMode,
   3919     (void *)NineDevice9_SetGammaRamp,
   3920     (void *)NineDevice9_GetGammaRamp,
   3921     (void *)NineDevice9_CreateTexture,
   3922     (void *)NineDevice9_CreateVolumeTexture,
   3923     (void *)NineDevice9_CreateCubeTexture,
   3924     (void *)NineDevice9_CreateVertexBuffer,
   3925     (void *)NineDevice9_CreateIndexBuffer,
   3926     (void *)NineDevice9_CreateRenderTarget,
   3927     (void *)NineDevice9_CreateDepthStencilSurface,
   3928     (void *)NineDevice9_UpdateSurface,
   3929     (void *)NineDevice9_UpdateTexture,
   3930     (void *)NineDevice9_GetRenderTargetData,
   3931     (void *)NineDevice9_GetFrontBufferData,
   3932     (void *)NineDevice9_StretchRect,
   3933     (void *)NineDevice9_ColorFill,
   3934     (void *)NineDevice9_CreateOffscreenPlainSurface,
   3935     (void *)NineDevice9_SetRenderTarget,
   3936     (void *)NineDevice9_GetRenderTarget,
   3937     (void *)NineDevice9_SetDepthStencilSurface,
   3938     (void *)NineDevice9_GetDepthStencilSurface,
   3939     (void *)NineDevice9_BeginScene,
   3940     (void *)NineDevice9_EndScene,
   3941     (void *)NineDevice9_Clear,
   3942     (void *)NineDevice9_SetTransform,
   3943     (void *)NineDevice9_GetTransform,
   3944     (void *)NineDevice9_MultiplyTransform,
   3945     (void *)NineDevice9_SetViewport,
   3946     (void *)NineDevice9_GetViewport,
   3947     (void *)NineDevice9_SetMaterial,
   3948     (void *)NineDevice9_GetMaterial,
   3949     (void *)NineDevice9_SetLight,
   3950     (void *)NineDevice9_GetLight,
   3951     (void *)NineDevice9_LightEnable,
   3952     (void *)NineDevice9_GetLightEnable,
   3953     (void *)NineDevice9_SetClipPlane,
   3954     (void *)NineDevice9_GetClipPlane,
   3955     (void *)NineDevice9_SetRenderState,
   3956     (void *)NineDevice9_GetRenderState,
   3957     (void *)NineDevice9_CreateStateBlock,
   3958     (void *)NineDevice9_BeginStateBlock,
   3959     (void *)NineDevice9_EndStateBlock,
   3960     (void *)NineDevice9_SetClipStatus,
   3961     (void *)NineDevice9_GetClipStatus,
   3962     (void *)NineDevice9_GetTexture,
   3963     (void *)NineDevice9_SetTexture,
   3964     (void *)NineDevice9_GetTextureStageState,
   3965     (void *)NineDevice9_SetTextureStageState,
   3966     (void *)NineDevice9_GetSamplerState,
   3967     (void *)NineDevice9_SetSamplerState,
   3968     (void *)NineDevice9_ValidateDevice,
   3969     (void *)NineDevice9_SetPaletteEntries,
   3970     (void *)NineDevice9_GetPaletteEntries,
   3971     (void *)NineDevice9_SetCurrentTexturePalette,
   3972     (void *)NineDevice9_GetCurrentTexturePalette,
   3973     (void *)NineDevice9_SetScissorRect,
   3974     (void *)NineDevice9_GetScissorRect,
   3975     (void *)NineDevice9_SetSoftwareVertexProcessing,
   3976     (void *)NineDevice9_GetSoftwareVertexProcessing,
   3977     (void *)NineDevice9_SetNPatchMode,
   3978     (void *)NineDevice9_GetNPatchMode,
   3979     (void *)NineDevice9_DrawPrimitive,
   3980     (void *)NineDevice9_DrawIndexedPrimitive,
   3981     (void *)NineDevice9_DrawPrimitiveUP,
   3982     (void *)NineDevice9_DrawIndexedPrimitiveUP,
   3983     (void *)NineDevice9_ProcessVertices,
   3984     (void *)NineDevice9_CreateVertexDeclaration,
   3985     (void *)NineDevice9_SetVertexDeclaration,
   3986     (void *)NineDevice9_GetVertexDeclaration,
   3987     (void *)NineDevice9_SetFVF,
   3988     (void *)NineDevice9_GetFVF,
   3989     (void *)NineDevice9_CreateVertexShader,
   3990     (void *)NineDevice9_SetVertexShader,
   3991     (void *)NineDevice9_GetVertexShader,
   3992     (void *)NineDevice9_SetVertexShaderConstantF,
   3993     (void *)NineDevice9_GetVertexShaderConstantF,
   3994     (void *)NineDevice9_SetVertexShaderConstantI,
   3995     (void *)NineDevice9_GetVertexShaderConstantI,
   3996     (void *)NineDevice9_SetVertexShaderConstantB,
   3997     (void *)NineDevice9_GetVertexShaderConstantB,
   3998     (void *)NineDevice9_SetStreamSource,
   3999     (void *)NineDevice9_GetStreamSource,
   4000     (void *)NineDevice9_SetStreamSourceFreq,
   4001     (void *)NineDevice9_GetStreamSourceFreq,
   4002     (void *)NineDevice9_SetIndices,
   4003     (void *)NineDevice9_GetIndices,
   4004     (void *)NineDevice9_CreatePixelShader,
   4005     (void *)NineDevice9_SetPixelShader,
   4006     (void *)NineDevice9_GetPixelShader,
   4007     (void *)NineDevice9_SetPixelShaderConstantF,
   4008     (void *)NineDevice9_GetPixelShaderConstantF,
   4009     (void *)NineDevice9_SetPixelShaderConstantI,
   4010     (void *)NineDevice9_GetPixelShaderConstantI,
   4011     (void *)NineDevice9_SetPixelShaderConstantB,
   4012     (void *)NineDevice9_GetPixelShaderConstantB,
   4013     (void *)NineDevice9_DrawRectPatch,
   4014     (void *)NineDevice9_DrawTriPatch,
   4015     (void *)NineDevice9_DeletePatch,
   4016     (void *)NineDevice9_CreateQuery
   4017 };
   4018 
   4019 static const GUID *NineDevice9_IIDs[] = {
   4020     &IID_IDirect3DDevice9,
   4021     &IID_IUnknown,
   4022     NULL
   4023 };
   4024 
   4025 HRESULT
   4026 NineDevice9_new( struct pipe_screen *pScreen,
   4027                  D3DDEVICE_CREATION_PARAMETERS *pCreationParameters,
   4028                  D3DCAPS9 *pCaps,
   4029                  D3DPRESENT_PARAMETERS *pPresentationParameters,
   4030                  IDirect3D9 *pD3D9,
   4031                  ID3DPresentGroup *pPresentationGroup,
   4032                  struct d3dadapter9_context *pCTX,
   4033                  boolean ex,
   4034                  D3DDISPLAYMODEEX *pFullscreenDisplayMode,
   4035                  struct NineDevice9 **ppOut,
   4036                  int minorVersionNum )
   4037 {
   4038     BOOL lock;
   4039     lock = !!(pCreationParameters->BehaviorFlags & D3DCREATE_MULTITHREADED);
   4040 
   4041     NINE_NEW(Device9, ppOut, lock, /* args */
   4042              pScreen, pCreationParameters, pCaps,
   4043              pPresentationParameters, pD3D9, pPresentationGroup, pCTX,
   4044              ex, pFullscreenDisplayMode, minorVersionNum );
   4045 }
   4046