HRESULT NINE_WINAPI NineAdapter9_CheckDepthStencilMatch( struct NineAdapter9 *This, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat ) { struct pipe_screen *screen; enum pipe_format dfmt, bfmt, zsfmt; HRESULT hr; DBG("This=%p DeviceType=%s AdapterFormat=%s " "RenderTargetFormat=%s DepthStencilFormat=%s\n", This, nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat), d3dformat_to_string(RenderTargetFormat), d3dformat_to_string(DepthStencilFormat)); user_assert(display_format(AdapterFormat, FALSE), D3DERR_NOTAVAILABLE); user_assert(depth_stencil_format(DepthStencilFormat), D3DERR_NOTAVAILABLE); hr = NineAdapter9_GetScreen(This, DeviceType, &screen); if (FAILED(hr)) { return hr; } dfmt = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SHARED, FALSE, FALSE); bfmt = d3d9_to_pipe_format_checked(screen, RenderTargetFormat, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET, FALSE, FALSE); if (RenderTargetFormat == D3DFMT_NULL) bfmt = dfmt; zsfmt = d3d9_to_pipe_format_checked(screen, DepthStencilFormat, PIPE_TEXTURE_2D, 0, d3d9_get_pipe_depth_format_bindings(DepthStencilFormat), FALSE, FALSE); if (dfmt == PIPE_FORMAT_NONE || bfmt == PIPE_FORMAT_NONE || zsfmt == PIPE_FORMAT_NONE) { return D3DERR_NOTAVAILABLE; } return D3D_OK; }
HRESULT WINAPI NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels ) { struct pipe_screen *screen; HRESULT hr; enum pipe_format pf; unsigned bind; DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u " "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType, pQualityLevels); hr = NineAdapter9_GetScreen(This, DeviceType, &screen); if (FAILED(hr)) return hr; if (depth_stencil_format(SurfaceFormat)) bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat); else /* render-target */ bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE | PIPE_BIND_RENDER_TARGET; pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, MultiSampleType, bind, FALSE); if (pf == PIPE_FORMAT_NONE) { DBG("%s with %u samples not available.\n", d3dformat_to_string(SurfaceFormat), MultiSampleType); return D3DERR_NOTAVAILABLE; } if (pQualityLevels) *pQualityLevels = 1; /* gallium doesn't have quality levels */ return D3D_OK; }
HRESULT NINE_WINAPI NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat, BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType, DWORD *pQualityLevels ) { struct pipe_screen *screen; HRESULT hr; enum pipe_format pf; unsigned bind; DBG("This=%p DeviceType=%s SurfaceFormat=%s Windowed=%i MultiSampleType=%u " "pQualityLevels=%p\n", This, nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(SurfaceFormat), Windowed, MultiSampleType, pQualityLevels); if (pQualityLevels) { /* In error cases return only 1 quality level supported */ *pQualityLevels = 1; } user_assert(MultiSampleType <= D3DMULTISAMPLE_16_SAMPLES, D3DERR_INVALIDCALL); hr = NineAdapter9_GetScreen(This, DeviceType, &screen); if (FAILED(hr)) return hr; if (depth_stencil_format(SurfaceFormat)) bind = d3d9_get_pipe_depth_format_bindings(SurfaceFormat); else /* render-target */ bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, FALSE, FALSE); if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { DBG("%s not available.\n", d3dformat_to_string(SurfaceFormat)); return D3DERR_INVALIDCALL; } pf = d3d9_to_pipe_format_checked(screen, SurfaceFormat, PIPE_TEXTURE_2D, MultiSampleType, bind, FALSE, FALSE); if (pf == PIPE_FORMAT_NONE && SurfaceFormat != D3DFMT_NULL) { DBG("%s with %u samples not available.\n", d3dformat_to_string(SurfaceFormat), MultiSampleType); return D3DERR_NOTAVAILABLE; } if (pQualityLevels) { /* NONMASKABLE MultiSampleType might have more than one quality level, * while MASKABLE MultiSampleTypes have only one level. * Advertise quality levels and map each level to a sample count. */ (void ) d3dmultisample_type_check(screen, SurfaceFormat, &MultiSampleType, D3DMULTISAMPLE_16_SAMPLES, pQualityLevels); DBG("advertising %u quality levels\n", *pQualityLevels); } return D3D_OK; }
HRESULT NINE_WINAPI NineAdapter9_CheckDeviceFormat( struct NineAdapter9 *This, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat, DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat ) { struct pipe_screen *screen; HRESULT hr; enum pipe_format pf; enum pipe_texture_target target; unsigned bind = 0; boolean srgb; /* Check adapter format. */ DBG("This=%p DeviceType=%s AdapterFormat=%s\n", This, nine_D3DDEVTYPE_to_str(DeviceType), d3dformat_to_string(AdapterFormat)); DBG("Usage=%x RType=%u CheckFormat=%s\n", Usage, RType, d3dformat_to_string(CheckFormat)); user_assert(display_format(AdapterFormat, FALSE), D3DERR_INVALIDCALL); hr = NineAdapter9_GetScreen(This, DeviceType, &screen); if (FAILED(hr)) return hr; pf = d3d9_to_pipe_format_checked(screen, AdapterFormat, PIPE_TEXTURE_2D, 0, PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SHARED, FALSE, FALSE); if (pf == PIPE_FORMAT_NONE) { DBG("AdapterFormat %s not available.\n", d3dformat_to_string(AdapterFormat)); return D3DERR_NOTAVAILABLE; } /* Check actual format. */ switch (RType) { case D3DRTYPE_SURFACE: target = PIPE_TEXTURE_2D; break; case D3DRTYPE_TEXTURE: target = PIPE_TEXTURE_2D; break; case D3DRTYPE_CUBETEXTURE: target = PIPE_TEXTURE_CUBE; break; case D3DRTYPE_VOLUME: target = PIPE_TEXTURE_3D; break; case D3DRTYPE_VOLUMETEXTURE: target = PIPE_TEXTURE_3D; break; case D3DRTYPE_VERTEXBUFFER: target = PIPE_BUFFER; break; case D3DRTYPE_INDEXBUFFER: target = PIPE_BUFFER; break; default: user_assert(0, D3DERR_INVALIDCALL); } bind = 0; if (Usage & D3DUSAGE_RENDERTARGET) bind |= PIPE_BIND_RENDER_TARGET; if (Usage & D3DUSAGE_DEPTHSTENCIL) { if (!depth_stencil_format(CheckFormat)) return D3DERR_NOTAVAILABLE; bind |= d3d9_get_pipe_depth_format_bindings(CheckFormat); } /* API hack because setting RT[0] to NULL is forbidden */ if (CheckFormat == D3DFMT_NULL && bind == PIPE_BIND_RENDER_TARGET && (RType == D3DRTYPE_SURFACE || RType == D3DRTYPE_TEXTURE)) return D3D_OK; /* RESZ hack */ if (CheckFormat == D3DFMT_RESZ && bind == PIPE_BIND_RENDER_TARGET && RType == D3DRTYPE_SURFACE) return screen->get_param(screen, PIPE_CAP_MULTISAMPLE_Z_RESOLVE) ? D3D_OK : D3DERR_NOTAVAILABLE; /* ATOC hack */ if (CheckFormat == D3DFMT_ATOC && RType == D3DRTYPE_SURFACE) return D3D_OK; if ((Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING) && (Usage & D3DUSAGE_RENDERTARGET)) bind |= PIPE_BIND_BLENDABLE; if (Usage & D3DUSAGE_DMAP) { DBG("D3DUSAGE_DMAP not available\n"); return D3DERR_NOTAVAILABLE; /* TODO: displacement mapping */ } switch (RType) { case D3DRTYPE_TEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; case D3DRTYPE_CUBETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; case D3DRTYPE_VOLUMETEXTURE: bind |= PIPE_BIND_SAMPLER_VIEW; break; case D3DRTYPE_VERTEXBUFFER: bind |= PIPE_BIND_VERTEX_BUFFER; break; case D3DRTYPE_INDEXBUFFER: bind |= PIPE_BIND_INDEX_BUFFER; break; case D3DRTYPE_SURFACE: if (!(Usage & D3DUSAGE_DEPTHSTENCIL)) bind |= PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ /* Offscreen surface support: Usage = 0. * In practice drivers are very restrictive on the formats supported. * Basically a few common formats + YUV and compressed formats. The * reason is that offscreen surface are useful only for directdraw * compatibility (a WONTIMPL of nine) + format conversion (useful in * particular for YUV because the format was not advertised for textures * on NV chips). */ if (Usage == 0) bind |= PIPE_BIND_RENDER_TARGET; /* A current requirement of our impl, which we should get rid of. */ default: break; } srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0; pf = d3d9_to_pipe_format_checked(screen, CheckFormat, target, 0, bind, srgb, FALSE); if (pf == PIPE_FORMAT_NONE) { DBG("NOT AVAILABLE\n"); return D3DERR_NOTAVAILABLE; } /* we support ATI1 and ATI2 hack only for 2D and Cube textures */ if (RType != D3DRTYPE_TEXTURE && RType != D3DRTYPE_CUBETEXTURE && (CheckFormat == D3DFMT_ATI1 || CheckFormat == D3DFMT_ATI2)) return D3DERR_NOTAVAILABLE; /* if (Usage & D3DUSAGE_NONSECURE) { don't know the implications of this } */ /* if (Usage & D3DUSAGE_SOFTWAREPROCESSING) { we can always support this } */ if ((Usage & D3DUSAGE_AUTOGENMIPMAP) && !(bind & PIPE_BIND_SAMPLER_VIEW)) return D3DOK_NOAUTOGEN; return D3D_OK; }
HRESULT NineSwapChain9_Resize( struct NineSwapChain9 *This, D3DPRESENT_PARAMETERS *pParams, D3DDISPLAYMODEEX *mode ) { struct NineDevice9 *pDevice = This->base.device; D3DSURFACE_DESC desc; HRESULT hr; struct pipe_resource *resource, tmplt; enum pipe_format pf; BOOL has_present_buffers = FALSE; int depth; unsigned i, oldBufferCount, newBufferCount; D3DMULTISAMPLE_TYPE multisample_type; DBG("This=%p pParams=%p\n", This, pParams); user_assert(pParams != NULL, E_POINTER); user_assert(pParams->SwapEffect, D3DERR_INVALIDCALL); user_assert((pParams->SwapEffect != D3DSWAPEFFECT_COPY) || (pParams->BackBufferCount <= 1), D3DERR_INVALIDCALL); user_assert(pDevice->ex || pParams->BackBufferCount <= D3DPRESENT_BACK_BUFFERS_MAX, D3DERR_INVALIDCALL); user_assert(!pDevice->ex || pParams->BackBufferCount <= D3DPRESENT_BACK_BUFFERS_MAX_EX, D3DERR_INVALIDCALL); user_assert(pDevice->ex || (pParams->SwapEffect == D3DSWAPEFFECT_FLIP) || (pParams->SwapEffect == D3DSWAPEFFECT_COPY) || (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD), D3DERR_INVALIDCALL); DBG("pParams(%p):\n" "BackBufferWidth: %u\n" "BackBufferHeight: %u\n" "BackBufferFormat: %s\n" "BackBufferCount: %u\n" "MultiSampleType: %u\n" "MultiSampleQuality: %u\n" "SwapEffect: %u\n" "hDeviceWindow: %p\n" "Windowed: %i\n" "EnableAutoDepthStencil: %i\n" "AutoDepthStencilFormat: %s\n" "Flags: %s\n" "FullScreen_RefreshRateInHz: %u\n" "PresentationInterval: %x\n", pParams, pParams->BackBufferWidth, pParams->BackBufferHeight, d3dformat_to_string(pParams->BackBufferFormat), pParams->BackBufferCount, pParams->MultiSampleType, pParams->MultiSampleQuality, pParams->SwapEffect, pParams->hDeviceWindow, pParams->Windowed, pParams->EnableAutoDepthStencil, d3dformat_to_string(pParams->AutoDepthStencilFormat), nine_D3DPRESENTFLAG_to_str(pParams->Flags), pParams->FullScreen_RefreshRateInHz, pParams->PresentationInterval); if (pParams->BackBufferCount == 0) { pParams->BackBufferCount = 1; } if (pParams->BackBufferFormat == D3DFMT_UNKNOWN) { pParams->BackBufferFormat = D3DFMT_A8R8G8B8; } This->desired_fences = This->actx->throttling ? This->actx->throttling_value + 1 : 0; /* +1 because we add the fence of the current buffer before popping an old one */ if (This->desired_fences > DRI_SWAP_FENCES_MAX) This->desired_fences = DRI_SWAP_FENCES_MAX; if (This->actx->vblank_mode == 0) pParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; else if (This->actx->vblank_mode == 3) pParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE; if (mode && This->mode) { *(This->mode) = *mode; } else if (mode) { This->mode = malloc(sizeof(D3DDISPLAYMODEEX)); memcpy(This->mode, mode, sizeof(D3DDISPLAYMODEEX)); } else { free(This->mode); This->mode = NULL; } /* Note: It is the role of the backend to fill if necessary * BackBufferWidth and BackBufferHeight */ hr = ID3DPresent_SetPresentParameters(This->present, pParams, This->mode); if (hr != D3D_OK) return hr; oldBufferCount = This->num_back_buffers; newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams); multisample_type = pParams->MultiSampleType; /* Map MultiSampleQuality to MultiSampleType */ hr = d3dmultisample_type_check(This->screen, pParams->BackBufferFormat, &multisample_type, pParams->MultiSampleQuality, NULL); if (FAILED(hr)) { return hr; } pf = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat, PIPE_TEXTURE_2D, multisample_type, PIPE_BIND_RENDER_TARGET, FALSE, FALSE); if (This->actx->linear_framebuffer || (pf != PIPE_FORMAT_B8G8R8X8_UNORM && pf != PIPE_FORMAT_B8G8R8A8_UNORM) || pParams->SwapEffect != D3DSWAPEFFECT_DISCARD || multisample_type >= 2 || (This->actx->ref && This->actx->ref == This->screen)) has_present_buffers = TRUE; /* Note: the buffer depth has to match the window depth. * In practice, ARGB buffers can be used with windows * of depth 24. Windows of depth 32 are extremely rare. * So even if the buffer is ARGB, say it is depth 24. * It is common practice, for example that's how * glamor implements depth 24. * TODO: handle windows with other depths. Not possible in the short term. * For example 16 bits.*/ depth = 24; memset(&tmplt, 0, sizeof(tmplt)); tmplt.target = PIPE_TEXTURE_2D; tmplt.width0 = pParams->BackBufferWidth; tmplt.height0 = pParams->BackBufferHeight; tmplt.depth0 = 1; tmplt.last_level = 0; tmplt.array_size = 1; tmplt.usage = PIPE_USAGE_DEFAULT; tmplt.flags = 0; desc.Type = D3DRTYPE_SURFACE; desc.Pool = D3DPOOL_DEFAULT; desc.MultiSampleType = pParams->MultiSampleType; desc.MultiSampleQuality = pParams->MultiSampleQuality; desc.Width = pParams->BackBufferWidth; desc.Height = pParams->BackBufferHeight; for (i = 0; i < oldBufferCount; i++) { if (This->tasks[i]) _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[i])); } memset(This->tasks, 0, sizeof(This->tasks)); if (This->pool) { _mesa_threadpool_destroy(This, This->pool); This->pool = NULL; } This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY); if (This->enable_threadpool) This->pool = _mesa_threadpool_create(This); if (!This->pool) This->enable_threadpool = FALSE; for (i = 0; i < oldBufferCount; i++) { ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]); This->present_handles[i] = NULL; if (This->present_buffers[i]) pipe_resource_reference(&(This->present_buffers[i]), NULL); } if (newBufferCount != oldBufferCount) { for (i = newBufferCount; i < oldBufferCount; ++i) NineUnknown_Detach(NineUnknown(This->buffers[i])); for (i = oldBufferCount; i < newBufferCount; ++i) { This->buffers[i] = NULL; This->present_handles[i] = NULL; } } This->num_back_buffers = newBufferCount; for (i = 0; i < newBufferCount; ++i) { tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; tmplt.nr_samples = multisample_type; if (!has_present_buffers) tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS; tmplt.format = d3d9_to_pipe_format_checked(This->screen, pParams->BackBufferFormat, PIPE_TEXTURE_2D, tmplt.nr_samples, tmplt.bind, FALSE, FALSE); if (tmplt.format == PIPE_FORMAT_NONE) return D3DERR_INVALIDCALL; resource = This->screen->resource_create(This->screen, &tmplt); if (!resource) { DBG("Failed to create pipe_resource.\n"); return D3DERR_OUTOFVIDEOMEMORY; } if (pParams->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; if (This->buffers[i]) { NineSurface9_SetMultiSampleType(This->buffers[i], desc.MultiSampleType); NineSurface9_SetResourceResize(This->buffers[i], resource); if (has_present_buffers) pipe_resource_reference(&resource, NULL); } else { desc.Format = pParams->BackBufferFormat; desc.Usage = D3DUSAGE_RENDERTARGET; hr = NineSurface9_new(pDevice, NineUnknown(This), resource, NULL, 0, 0, 0, &desc, &This->buffers[i]); if (has_present_buffers) pipe_resource_reference(&resource, NULL); if (FAILED(hr)) { DBG("Failed to create RT surface.\n"); return hr; } This->buffers[i]->base.base.forward = FALSE; } if (has_present_buffers) { tmplt.format = PIPE_FORMAT_B8G8R8X8_UNORM; tmplt.bind = NINE_BIND_PRESENTBUFFER_FLAGS; tmplt.nr_samples = 0; if (This->actx->linear_framebuffer) tmplt.bind |= PIPE_BIND_LINEAR; if (pParams->SwapEffect != D3DSWAPEFFECT_DISCARD) tmplt.bind |= PIPE_BIND_RENDER_TARGET; resource = This->screen->resource_create(This->screen, &tmplt); pipe_resource_reference(&(This->present_buffers[i]), resource); } This->present_handles[i] = D3DWindowBuffer_create(This, resource, depth, false); pipe_resource_reference(&resource, NULL); if (!This->present_handles[i]) { return D3DERR_DRIVERINTERNALERROR; } } if (pParams->EnableAutoDepthStencil) { tmplt.bind = d3d9_get_pipe_depth_format_bindings(pParams->AutoDepthStencilFormat); tmplt.nr_samples = multisample_type; tmplt.format = d3d9_to_pipe_format_checked(This->screen, pParams->AutoDepthStencilFormat, PIPE_TEXTURE_2D, tmplt.nr_samples, tmplt.bind, FALSE, FALSE); if (tmplt.format == PIPE_FORMAT_NONE) return D3DERR_INVALIDCALL; if (This->zsbuf) { resource = This->screen->resource_create(This->screen, &tmplt); if (!resource) { DBG("Failed to create pipe_resource for depth buffer.\n"); return D3DERR_OUTOFVIDEOMEMORY; } NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType); NineSurface9_SetResourceResize(This->zsbuf, resource); pipe_resource_reference(&resource, NULL); } else { hr = NineDevice9_CreateDepthStencilSurface(pDevice, pParams->BackBufferWidth, pParams->BackBufferHeight, pParams->AutoDepthStencilFormat, pParams->MultiSampleType, pParams->MultiSampleQuality, 0, (IDirect3DSurface9 **)&This->zsbuf, NULL); if (FAILED(hr)) { DBG("Failed to create ZS surface.\n"); return hr; } NineUnknown_ConvertRefToBind(NineUnknown(This->zsbuf)); } } This->params = *pParams; return D3D_OK; }
HRESULT NineSurface9_ctor( struct NineSurface9 *This, struct NineUnknownParams *pParams, struct NineUnknown *pContainer, struct pipe_resource *pResource, void *user_buffer, uint8_t TextureType, unsigned Level, unsigned Layer, D3DSURFACE_DESC *pDesc ) { HRESULT hr; union pipe_color_union rgba = {0}; struct pipe_surface *surf; struct pipe_context *pipe = pParams->device->pipe; bool allocate = !pContainer && pDesc->Format != D3DFMT_NULL; D3DMULTISAMPLE_TYPE multisample_type; DBG("This=%p pDevice=%p pResource=%p Level=%u Layer=%u pDesc=%p\n", This, pParams->device, pResource, Level, Layer, pDesc); /* Mark this as a special surface held by another internal resource. */ pParams->container = pContainer; /* Make sure there's a Desc */ assert(pDesc); /* D3DUSAGE_DYNAMIC isn't allowed on managed buffers */ user_assert(!(pDesc->Usage & D3DUSAGE_DYNAMIC) || (pDesc->Pool != D3DPOOL_MANAGED), D3DERR_INVALIDCALL); assert(allocate || pResource || user_buffer || pDesc->Format == D3DFMT_NULL); assert(!allocate || (!pResource && !user_buffer)); assert(!pResource || !user_buffer); assert(!user_buffer || pDesc->Pool != D3DPOOL_DEFAULT); assert(!pResource || pDesc->Pool == D3DPOOL_DEFAULT); /* Allocation only from create_zs_or_rt_surface with params 0 0 0 */ assert(!allocate || (Level == 0 && Layer == 0 && TextureType == 0)); This->data = (uint8_t *)user_buffer; multisample_type = pDesc->MultiSampleType; /* Map MultiSampleQuality to MultiSampleType */ hr = d3dmultisample_type_check(pParams->device->screen, pDesc->Format, &multisample_type, pDesc->MultiSampleQuality, NULL); if (FAILED(hr)) { return hr; } /* TODO: this is (except width and height) duplicate from * container info (in the pContainer case). Some refactoring is * needed to avoid duplication */ This->base.info.screen = pParams->device->screen; This->base.info.target = PIPE_TEXTURE_2D; This->base.info.width0 = pDesc->Width; This->base.info.height0 = pDesc->Height; This->base.info.depth0 = 1; This->base.info.last_level = 0; This->base.info.array_size = 1; This->base.info.nr_samples = multisample_type; This->base.info.usage = PIPE_USAGE_DEFAULT; This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ if (pDesc->Usage & D3DUSAGE_RENDERTARGET) { This->base.info.bind |= PIPE_BIND_RENDER_TARGET; } else if (pDesc->Usage & D3DUSAGE_DEPTHSTENCIL) { This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); if (TextureType) This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; } This->base.info.flags = 0; This->base.info.format = d3d9_to_pipe_format_checked(This->base.info.screen, pDesc->Format, This->base.info.target, This->base.info.nr_samples, This->base.info.bind, FALSE, pDesc->Pool == D3DPOOL_SCRATCH); if (This->base.info.format == PIPE_FORMAT_NONE && pDesc->Format != D3DFMT_NULL) return D3DERR_INVALIDCALL; if (allocate && compressed_format(pDesc->Format)) { const unsigned w = util_format_get_blockwidth(This->base.info.format); const unsigned h = util_format_get_blockheight(This->base.info.format); /* Note: In the !allocate case, the test could fail (lower levels of a texture) */ user_assert(!(pDesc->Width % w) && !(pDesc->Height % h), D3DERR_INVALIDCALL); } /* Get true format */ This->format_conversion = d3d9_to_pipe_format_checked(This->base.info.screen, pDesc->Format, This->base.info.target, This->base.info.nr_samples, This->base.info.bind, FALSE, TRUE); if (This->base.info.format != This->format_conversion) { This->data_conversion = align_calloc( nine_format_get_level_alloc_size(This->format_conversion, pDesc->Width, pDesc->Height, 0), 32); if (!This->data_conversion) return E_OUTOFMEMORY; This->stride_conversion = nine_format_get_stride(This->format_conversion, pDesc->Width); } if ((allocate && pDesc->Pool != D3DPOOL_DEFAULT) || pDesc->Format == D3DFMT_NULL) { /* Ram buffer with no parent. Has to allocate the resource itself */ assert(!user_buffer); This->data = align_calloc( nine_format_get_level_alloc_size(This->base.info.format, pDesc->Width, pDesc->Height, 0), 32); if (!This->data) return E_OUTOFMEMORY; } hr = NineResource9_ctor(&This->base, pParams, pResource, allocate && (pDesc->Pool == D3DPOOL_DEFAULT), D3DRTYPE_SURFACE, pDesc->Pool, pDesc->Usage); if (FAILED(hr)) return hr; This->pipe = This->base.base.device->pipe; This->transfer = NULL; This->texture = TextureType; This->level = Level; This->level_actual = Level; This->layer = Layer; This->desc = *pDesc; This->stride = nine_format_get_stride(This->base.info.format, pDesc->Width); if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; /* TODO: investigate what else exactly needs to be cleared */ if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) { surf = NineSurface9_GetSurface(This, 0); pipe->clear_render_target(pipe, surf, &rgba, 0, 0, pDesc->Width, pDesc->Height, false); } NineSurface9_Dump(This); return D3D_OK; }