void NineSwapChain9_dtor( struct NineSwapChain9 *This ) { unsigned i; DBG("This=%p\n", This); if (This->pool) _mesa_threadpool_destroy(This, This->pool); for (i = 0; i < This->num_back_buffers; i++) { if (This->buffers[i]) NineUnknown_Detach(NineUnknown(This->buffers[i])); if (This->present_handles[i]) ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]); if (This->present_buffers[i]) pipe_resource_reference(&(This->present_buffers[i]), NULL); } if (This->zsbuf) NineUnknown_Unbind(NineUnknown(This->zsbuf)); if (This->present) ID3DPresent_Release(This->present); swap_fences_unref(This); NineUnknown_dtor(&This->base); }
HRESULT NINE_WINAPI NineSurface9_GetContainer( struct NineSurface9 *This, REFIID riid, void **ppContainer ) { HRESULT hr; char guid_str[64]; DBG("This=%p riid=%p id=%s ppContainer=%p\n", This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); if (!ppContainer) return E_POINTER; /* Return device for OffscreenPlainSurface, DepthStencilSurface and RenderTarget */ if (!NineUnknown(This)->container) { *ppContainer = NineUnknown(This)->device; NineUnknown_AddRef(NineUnknown(*ppContainer)); return D3D_OK; } hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); if (FAILED(hr)) DBG("QueryInterface FAILED!\n"); return hr; }
HRESULT WINAPI NineVolume9_GetContainer( struct NineVolume9 *This, REFIID riid, void **ppContainer ) { if (!NineUnknown(This)->container) return E_NOINTERFACE; return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); }
HRESULT NINE_WINAPI NineSwapChain9_GetFrontBufferData( struct NineSwapChain9 *This, IDirect3DSurface9 *pDestSurface ) { struct NineSurface9 *dest_surface = NineSurface9(pDestSurface); struct NineDevice9 *pDevice = This->base.device; unsigned int width, height; struct pipe_resource *temp_resource; struct NineSurface9 *temp_surface; D3DWindowBuffer *temp_handle; D3DSURFACE_DESC desc; HRESULT hr; DBG("GetFrontBufferData: This=%p pDestSurface=%p\n", This, pDestSurface); user_assert(dest_surface->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL); width = dest_surface->desc.Width; height = dest_surface->desc.Height; /* Note: front window size and destination size are supposed * to match. However it's not very clear what should get taken in Windowed * mode. It may need a fix */ create_present_buffer(This, width, height, &temp_resource, &temp_handle); if (!temp_resource || !temp_handle) { return D3DERR_INVALIDCALL; } desc.Type = D3DRTYPE_SURFACE; desc.Pool = D3DPOOL_DEFAULT; desc.MultiSampleType = D3DMULTISAMPLE_NONE; desc.MultiSampleQuality = 0; desc.Width = width; desc.Height = height; /* NineSurface9_CopyDefaultToMem needs same format. */ desc.Format = dest_surface->desc.Format; desc.Usage = D3DUSAGE_RENDERTARGET; hr = NineSurface9_new(pDevice, NineUnknown(This), temp_resource, NULL, 0, 0, 0, &desc, &temp_surface); pipe_resource_reference(&temp_resource, NULL); if (FAILED(hr)) { DBG("Failed to create temp FrontBuffer surface.\n"); return hr; } ID3DPresent_FrontBufferCopy(This->present, temp_handle); NineSurface9_CopyDefaultToMem(dest_surface, temp_surface); ID3DPresent_DestroyD3DWindowBuffer(This->present, temp_handle); NineUnknown_Destroy(NineUnknown(temp_surface)); return D3D_OK; }
HRESULT WINAPI NineSurface9_GetContainer( struct NineSurface9 *This, REFIID riid, void **ppContainer ) { HRESULT hr; if (!NineUnknown(This)->container) return E_NOINTERFACE; hr = NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); if (FAILED(hr)) DBG("QueryInterface FAILED!\n"); return hr; }
HRESULT NINE_WINAPI NineVolume9_GetContainer( struct NineVolume9 *This, REFIID riid, void **ppContainer ) { char guid_str[64]; DBG("This=%p riid=%p id=%s ppContainer=%p\n", This, riid, riid ? GUID_sprintf(guid_str, riid) : "", ppContainer); if (!NineUnknown(This)->container) return E_NOINTERFACE; return NineUnknown_QueryInterface(NineUnknown(This)->container, riid, ppContainer); }
void NineSurface9_Dump( struct NineSurface9 *This ) { struct NineBaseTexture9 *tex; GUID id = IID_IDirect3DBaseTexture9; REFIID ref = &id; DBG("\nNineSurface9(%p->%p/%p): Pool=%s Type=%s Usage=%s\n" "Dims=%ux%u Format=%s Stride=%u Lockable=%i\n" "Level=%u(%u), Layer=%u\n", This, This->base.resource, This->data, nine_D3DPOOL_to_str(This->desc.Pool), nine_D3DRTYPE_to_str(This->desc.Type), nine_D3DUSAGE_to_str(This->desc.Usage), This->desc.Width, This->desc.Height, d3dformat_to_string(This->desc.Format), This->stride, This->base.resource && (This->base.resource->flags & NINE_RESOURCE_FLAG_LOCKABLE), This->level, This->level_actual, This->layer); if (!This->base.base.container) return; NineUnknown_QueryInterface(This->base.base.container, ref, (void **)&tex); if (tex) { NineBaseTexture9_Dump(tex); NineUnknown_Release(NineUnknown(tex)); } }
void NineSwapChain9_dtor( struct NineSwapChain9 *This ) { unsigned i; DBG("This=%p\n", This); if (This->buffers) { for (i = 0; i < This->params.BackBufferCount; i++) NineUnknown_Destroy(NineUnknown(This->buffers[i])); FREE(This->buffers); } if (This->zsbuf) NineUnknown_Destroy(NineUnknown(This->zsbuf)); if (This->present) ID3DPresent_Release(This->present); NineUnknown_dtor(&This->base); }
HRESULT NINE_WINAPI NineVolumeTexture9_GetVolumeLevel( struct NineVolumeTexture9 *This, UINT Level, IDirect3DVolume9 **ppVolumeLevel ) { user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->volumes[Level])); *ppVolumeLevel = (IDirect3DVolume9 *)This->volumes[Level]; return D3D_OK; }
HRESULT WINAPI NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer ) { (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO); user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL); user_assert(ppBackBuffer != NULL, E_POINTER); NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer])); *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer]; return D3D_OK; }
HRESULT WINAPI NineTexture9_GetSurfaceLevel( struct NineTexture9 *This, UINT Level, IDirect3DSurface9 **ppSurfaceLevel ) { user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->surfaces[Level])); *ppSurfaceLevel = (IDirect3DSurface9 *)This->surfaces[Level]; return D3D_OK; }
HRESULT NINE_WINAPI NineSwapChain9_GetBackBuffer( struct NineSwapChain9 *This, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer ) { DBG("GetBackBuffer: This=%p iBackBuffer=%d Type=%d ppBackBuffer=%p\n", This, iBackBuffer, Type, ppBackBuffer); (void)user_error(Type == D3DBACKBUFFER_TYPE_MONO); /* don't touch ppBackBuffer on error */ user_assert(ppBackBuffer != NULL, D3DERR_INVALIDCALL); user_assert(iBackBuffer < This->params.BackBufferCount, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->buffers[iBackBuffer])); *ppBackBuffer = (IDirect3DSurface9 *)This->buffers[iBackBuffer]; return D3D_OK; }
static inline void NineVolume9_MarkContainerDirty( struct NineVolume9 *This ) { struct NineBaseTexture9 *tex; #ifdef DEBUG /* This is always contained by a NineVolumeTexture9. */ GUID id = IID_IDirect3DVolumeTexture9; REFIID ref = &id; assert(NineUnknown_QueryInterface(This->base.container, ref, (void **)&tex) == S_OK); assert(NineUnknown_Release(NineUnknown(tex)) != 0); #endif tex = NineBaseTexture9(This->base.container); assert(tex); if (This->desc.Pool == D3DPOOL_MANAGED) tex->managed.dirty = TRUE; BASETEX_REGISTER_UPDATE(tex); }
HRESULT NINE_WINAPI NineCubeTexture9_GetCubeMapSurface( struct NineCubeTexture9 *This, D3DCUBEMAP_FACES FaceType, UINT Level, IDirect3DSurface9 **ppCubeMapSurface ) { const unsigned s = Level * 6 + FaceType; DBG("This=%p FaceType=%d Level=%u ppCubeMapSurface=%p\n", This, FaceType, Level, ppCubeMapSurface); user_assert(Level <= This->base.base.info.last_level, D3DERR_INVALIDCALL); user_assert(Level == 0 || !(This->base.base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); user_assert(FaceType < 6, D3DERR_INVALIDCALL); NineUnknown_AddRef(NineUnknown(This->surfaces[s])); *ppCubeMapSurface = (IDirect3DSurface9 *)This->surfaces[s]; return D3D_OK; }
HRESULT NineSwapChain9_Resize( struct NineSwapChain9 *This, D3DPRESENT_PARAMETERS *pParams ) { struct NineDevice9 *pDevice = This->base.device; struct NineSurface9 **bufs; D3DSURFACE_DESC desc; HRESULT hr; struct pipe_resource *resource, tmplt; unsigned i; DBG("This=%p pParams=%p\n", This, pParams); if (pParams) { 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->BackBufferFormat == D3DFMT_UNKNOWN) pParams->BackBufferFormat = This->params.BackBufferFormat; if (pParams->EnableAutoDepthStencil && This->params.EnableAutoDepthStencil && pParams->AutoDepthStencilFormat == D3DFMT_UNKNOWN) pParams->AutoDepthStencilFormat = This->params.AutoDepthStencilFormat; /* NULL means focus window. if (!pParams->hDeviceWindow && This->params.hDeviceWindow) pParams->hDeviceWindow = This->params.hDeviceWindow; */ if (pParams->BackBufferCount == 0) pParams->BackBufferCount = 1; /* ref MSDN */ if (pParams->BackBufferWidth == 0 || pParams->BackBufferHeight == 0) { RECT rect; if (!pParams->Windowed) return D3DERR_INVALIDCALL; if (FAILED(ID3DPresent_GetWindowRect(This->present, NULL, &rect))) { rect.right = This->params.BackBufferWidth; rect.bottom = This->params.BackBufferHeight; } if (!pParams->BackBufferWidth) pParams->BackBufferWidth = rect.right; if (!pParams->BackBufferHeight) pParams->BackBufferHeight = rect.bottom; } tmplt.target = PIPE_TEXTURE_2D; tmplt.width0 = pParams->BackBufferWidth; tmplt.height0 = pParams->BackBufferHeight; tmplt.depth0 = 1; tmplt.nr_samples = pParams->MultiSampleType; tmplt.last_level = 0; tmplt.array_size = 1; tmplt.usage = PIPE_USAGE_DEFAULT; tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; tmplt.flags = 0; desc.Type = D3DRTYPE_SURFACE; desc.Pool = D3DPOOL_DEFAULT; desc.MultiSampleType = pParams->MultiSampleType; desc.MultiSampleQuality = 0; desc.Width = pParams->BackBufferWidth; desc.Height = pParams->BackBufferHeight; if (pParams->BackBufferCount != This->params.BackBufferCount) { for (i = pParams->BackBufferCount; i < This->params.BackBufferCount; ++i) NineUnknown_Detach(NineUnknown(This->buffers[i])); bufs = REALLOC(This->buffers, This->params.BackBufferCount * sizeof(This->buffers[0]), pParams->BackBufferCount * sizeof(This->buffers[0])); if (!bufs) return E_OUTOFMEMORY; This->buffers = bufs; for (i = This->params.BackBufferCount; i < pParams->BackBufferCount; ++i) This->buffers[i] = NULL; } for (i = 0; i < pParams->BackBufferCount; ++i) { tmplt.format = d3d9_to_pipe_format(pParams->BackBufferFormat); tmplt.bind |= PIPE_BIND_RENDER_TARGET; 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_SetResourceResize(This->buffers[i], resource); pipe_resource_reference(&resource, NULL); } else { desc.Format = pParams->BackBufferFormat; desc.Usage = D3DUSAGE_RENDERTARGET; hr = NineSurface9_new(pDevice, NineUnknown(This), resource, 0, 0, 0, &desc, &This->buffers[i]); 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 (pParams->EnableAutoDepthStencil) { tmplt.format = d3d9_to_pipe_format(pParams->AutoDepthStencilFormat); tmplt.bind &= ~PIPE_BIND_RENDER_TARGET; tmplt.bind |= PIPE_BIND_DEPTH_STENCIL; resource = This->screen->resource_create(This->screen, &tmplt); if (!resource) { DBG("Failed to create pipe_resource for depth buffer.\n"); return D3DERR_OUTOFVIDEOMEMORY; } if (This->zsbuf) { NineSurface9_SetResourceResize(This->zsbuf, resource); pipe_resource_reference(&resource, NULL); } else { /* XXX wine thinks the container of this should the the device */ desc.Format = pParams->AutoDepthStencilFormat; desc.Usage = D3DUSAGE_DEPTHSTENCIL; hr = NineSurface9_new(pDevice, NineUnknown(pDevice), resource, 0, 0, 0, &desc, &This->zsbuf); pipe_resource_reference(&resource, NULL); if (FAILED(hr)) { DBG("Failed to create ZS surface.\n"); return hr; } This->zsbuf->base.base.forward = FALSE; } } This->params = *pParams; return D3D_OK; }
static HRESULT NineCubeTexture9_ctor( struct NineCubeTexture9 *This, struct NineUnknownParams *pParams, UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, HANDLE *pSharedHandle ) { struct pipe_resource *info = &This->base.base.info; struct pipe_screen *screen = pParams->device->screen; enum pipe_format pf; unsigned i, l, f, offset, face_size = 0; unsigned *level_offsets = NULL; D3DSURFACE_DESC sfdesc; void *p; HRESULT hr; DBG("This=%p pParams=%p EdgeLength=%u Levels=%u Usage=%d " "Format=%d Pool=%d pSharedHandle=%p\n", This, pParams, EdgeLength, Levels, Usage, Format, Pool, pSharedHandle); user_assert(EdgeLength, D3DERR_INVALIDCALL); /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || (Pool != D3DPOOL_SYSTEMMEM && Levels <= 1), D3DERR_INVALIDCALL); if (Usage & D3DUSAGE_AUTOGENMIPMAP) Levels = 0; pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_CUBE, 0, PIPE_BIND_SAMPLER_VIEW, FALSE, Pool == D3DPOOL_SCRATCH); if (pf == PIPE_FORMAT_NONE) return D3DERR_INVALIDCALL; if (compressed_format(Format)) { const unsigned w = util_format_get_blockwidth(pf); const unsigned h = util_format_get_blockheight(pf); user_assert(!(EdgeLength % w) && !(EdgeLength % h), D3DERR_INVALIDCALL); } info->screen = pParams->device->screen; info->target = PIPE_TEXTURE_CUBE; info->format = pf; info->width0 = EdgeLength; info->height0 = EdgeLength; info->depth0 = 1; if (Levels) info->last_level = Levels - 1; else info->last_level = util_logbase2(EdgeLength); info->array_size = 6; info->nr_samples = 0; info->bind = PIPE_BIND_SAMPLER_VIEW; info->usage = PIPE_USAGE_DEFAULT; info->flags = 0; if (Usage & D3DUSAGE_RENDERTARGET) info->bind |= PIPE_BIND_RENDER_TARGET; if (Usage & D3DUSAGE_DEPTHSTENCIL) info->bind |= PIPE_BIND_DEPTH_STENCIL; if (Usage & D3DUSAGE_DYNAMIC) { info->usage = PIPE_USAGE_DYNAMIC; info->bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; } if (Usage & D3DUSAGE_SOFTWAREPROCESSING) DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); if (Pool != D3DPOOL_DEFAULT) { level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); face_size = nine_format_get_size_and_offsets(pf, level_offsets, EdgeLength, EdgeLength, info->last_level); This->managed_buffer = align_malloc(6 * face_size, 32); if (!This->managed_buffer) return E_OUTOFMEMORY; } This->surfaces = CALLOC(6 * (info->last_level + 1), sizeof(*This->surfaces)); if (!This->surfaces) return E_OUTOFMEMORY; hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_CUBETEXTURE, Format, Pool, Usage); if (FAILED(hr)) return hr; This->base.pstype = 2; /* Create all the surfaces right away. * They manage backing storage, and transfers (LockRect) are deferred * to them. */ sfdesc.Format = Format; sfdesc.Type = D3DRTYPE_SURFACE; sfdesc.Usage = Usage; sfdesc.Pool = Pool; sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; sfdesc.MultiSampleQuality = 0; /* We allocate the memory for the surfaces as continous blocks. * This is the expected behaviour, however we haven't tested for * cube textures in which order the faces/levels should be in memory */ for (f = 0; f < 6; f++) { offset = f * face_size; for (l = 0; l <= info->last_level; l++) { sfdesc.Width = sfdesc.Height = u_minify(EdgeLength, l); p = This->managed_buffer ? This->managed_buffer + offset + level_offsets[l] : NULL; hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), This->base.base.resource, p, D3DRTYPE_CUBETEXTURE, l, f, &sfdesc, &This->surfaces[f + 6 * l]); if (FAILED(hr)) return hr; } } for (i = 0; i < 6; ++i) { /* Textures start initially dirty */ This->dirty_rect[i].width = EdgeLength; This->dirty_rect[i].height = EdgeLength; This->dirty_rect[i].depth = 1; } 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; }
static HRESULT NineTexture9_ctor( struct NineTexture9 *This, struct NineUnknownParams *pParams, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, HANDLE *pSharedHandle ) { struct pipe_screen *screen = pParams->device->screen; struct pipe_resource *info = &This->base.base.info; enum pipe_format pf; unsigned *level_offsets; unsigned l; D3DSURFACE_DESC sfdesc; HRESULT hr; void *user_buffer = NULL, *user_buffer_for_level; DBG("(%p) Width=%u Height=%u Levels=%u Usage=%s Format=%s Pool=%s " "pSharedHandle=%p\n", This, Width, Height, Levels, nine_D3DUSAGE_to_str(Usage), d3dformat_to_string(Format), nine_D3DPOOL_to_str(Pool), pSharedHandle); user_assert(Width && Height, D3DERR_INVALIDCALL); /* pSharedHandle: can be non-null for ex only. * D3DPOOL_SYSTEMMEM: Levels must be 1 * D3DPOOL_DEFAULT: no restriction for Levels * Other Pools are forbidden. */ user_assert(!pSharedHandle || pParams->device->ex, D3DERR_INVALIDCALL); user_assert(!pSharedHandle || (Pool == D3DPOOL_SYSTEMMEM && Levels == 1) || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP) || (Pool != D3DPOOL_SYSTEMMEM && Pool != D3DPOOL_SCRATCH && Levels <= 1), D3DERR_INVALIDCALL); /* TODO: implement pSharedHandle for D3DPOOL_DEFAULT (cross process * buffer sharing). * * Gem names may have fit but they're depreciated and won't work on render-nodes. * One solution is to use shm buffers. We would use a /dev/shm file, fill the first * values to tell it is a nine buffer, the size, which function created it, etc, * and then it would contain the data. The handle would be a number, corresponding to * the file to read (/dev/shm/nine-share-4 for example would be 4). * * Wine just ignores the argument, which works only if the app creates the handle * and won't use it. Instead of failing, we support that situation by putting an * invalid handle, that we would fail to import. Please note that we don't advertise * the flag indicating the support for that feature, but apps seem to not care. */ if (pSharedHandle && Pool == D3DPOOL_DEFAULT) { if (!*pSharedHandle) { DBG("Creating Texture with invalid handle. Importing will fail\n."); *pSharedHandle = (HANDLE)1; /* Wine would keep it NULL */ pSharedHandle = NULL; } else { ERR("Application tries to use cross-process sharing feature. Nine " "doesn't support it"); return D3DERR_INVALIDCALL; } } if (Usage & D3DUSAGE_AUTOGENMIPMAP) Levels = 0; pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, FALSE, Pool == D3DPOOL_SCRATCH); if (Format != D3DFMT_NULL && pf == PIPE_FORMAT_NONE) return D3DERR_INVALIDCALL; if (compressed_format(Format)) { const unsigned w = util_format_get_blockwidth(pf); const unsigned h = util_format_get_blockheight(pf); user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); } info->screen = screen; info->target = PIPE_TEXTURE_2D; info->format = pf; info->width0 = Width; info->height0 = Height; info->depth0 = 1; if (Levels) info->last_level = Levels - 1; else info->last_level = util_logbase2(MAX2(Width, Height)); info->array_size = 1; info->nr_samples = 0; info->nr_storage_samples = 0; info->bind = PIPE_BIND_SAMPLER_VIEW; info->usage = PIPE_USAGE_DEFAULT; info->flags = 0; if (Usage & D3DUSAGE_RENDERTARGET) info->bind |= PIPE_BIND_RENDER_TARGET; if (Usage & D3DUSAGE_DEPTHSTENCIL) info->bind |= PIPE_BIND_DEPTH_STENCIL; if (Usage & D3DUSAGE_DYNAMIC) { info->usage = PIPE_USAGE_DYNAMIC; } if (Usage & D3DUSAGE_SOFTWAREPROCESSING) DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); if (pSharedHandle && *pSharedHandle) { /* Pool == D3DPOOL_SYSTEMMEM */ user_buffer = (void *)*pSharedHandle; level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); (void) nine_format_get_size_and_offsets(pf, level_offsets, Width, Height, info->last_level); } else if (Pool != D3DPOOL_DEFAULT) { /* TODO: For D3DUSAGE_AUTOGENMIPMAP, it is likely we only have to * allocate only for the first level, since it is the only lockable * level. Check apps don't crash if we allocate smaller buffer (some * apps access sublevels of texture even if they locked only first * level) */ level_offsets = alloca(sizeof(unsigned) * (info->last_level + 1)); user_buffer = align_calloc( nine_format_get_size_and_offsets(pf, level_offsets, Width, Height, info->last_level), 32); This->managed_buffer = user_buffer; if (!This->managed_buffer) return E_OUTOFMEMORY; } This->surfaces = CALLOC(info->last_level + 1, sizeof(*This->surfaces)); if (!This->surfaces) return E_OUTOFMEMORY; hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_TEXTURE, Format, Pool, Usage); if (FAILED(hr)) return hr; This->base.pstype = (Height == 1) ? 1 : 0; /* Create all the surfaces right away. * They manage backing storage, and transfers (LockRect) are deferred * to them. */ sfdesc.Format = Format; sfdesc.Type = D3DRTYPE_SURFACE; sfdesc.Usage = Usage; sfdesc.Pool = Pool; sfdesc.MultiSampleType = D3DMULTISAMPLE_NONE; sfdesc.MultiSampleQuality = 0; for (l = 0; l <= info->last_level; ++l) { sfdesc.Width = u_minify(Width, l); sfdesc.Height = u_minify(Height, l); /* Some apps expect the memory to be allocated in * continous blocks */ user_buffer_for_level = user_buffer ? user_buffer + level_offsets[l] : NULL; hr = NineSurface9_new(This->base.base.base.device, NineUnknown(This), This->base.base.resource, user_buffer_for_level, D3DRTYPE_TEXTURE, l, 0, &sfdesc, &This->surfaces[l]); if (FAILED(hr)) return hr; } /* Textures start initially dirty */ This->dirty_rect.width = Width; This->dirty_rect.height = Height; This->dirty_rect.depth = 1; /* widht == 0 means empty, depth stays 1 */ if (pSharedHandle && !*pSharedHandle) {/* Pool == D3DPOOL_SYSTEMMEM */ *pSharedHandle = This->surfaces[0]->data; } return D3D_OK; }
static HRESULT NineVolumeTexture9_ctor( struct NineVolumeTexture9 *This, struct NineUnknownParams *pParams, UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, HANDLE *pSharedHandle ) { struct pipe_resource *info = &This->base.base.info; struct pipe_screen *screen = pParams->device->screen; enum pipe_format pf; unsigned l; D3DVOLUME_DESC voldesc; HRESULT hr; DBG("This=%p pParams=%p Width=%u Height=%u Depth=%u Levels=%u " "Usage=%d Format=%d Pool=%d pSharedHandle=%p\n", This, pParams, Width, Height, Depth, Levels, Usage, Format, Pool, pSharedHandle); user_assert(Width && Height && Depth, D3DERR_INVALIDCALL); /* user_assert(!pSharedHandle || Pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL); */ user_assert(!pSharedHandle, D3DERR_INVALIDCALL); /* TODO */ /* An IDirect3DVolume9 cannot be bound as a render target can it ? */ user_assert(!(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)), D3DERR_INVALIDCALL); user_assert(!(Usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL); pf = d3d9_to_pipe_format_checked(screen, Format, PIPE_TEXTURE_3D, 0, PIPE_BIND_SAMPLER_VIEW, FALSE, Pool == D3DPOOL_SCRATCH); if (pf == PIPE_FORMAT_NONE) return D3DERR_INVALIDCALL; /* We support ATI1 and ATI2 hacks only for 2D and Cube textures */ if (Format == D3DFMT_ATI1 || Format == D3DFMT_ATI2) return D3DERR_INVALIDCALL; if (compressed_format(Format)) { const unsigned w = util_format_get_blockwidth(pf); const unsigned h = util_format_get_blockheight(pf); /* Compressed formats are not compressed on depth component */ user_assert(!(Width % w) && !(Height % h), D3DERR_INVALIDCALL); } info->screen = pParams->device->screen; info->target = PIPE_TEXTURE_3D; info->format = pf; info->width0 = Width; info->height0 = Height; info->depth0 = Depth; if (Levels) info->last_level = Levels - 1; else info->last_level = util_logbase2(MAX2(MAX2(Width, Height), Depth)); info->array_size = 1; info->nr_samples = 0; info->bind = PIPE_BIND_SAMPLER_VIEW; info->usage = PIPE_USAGE_DEFAULT; info->flags = 0; if (Usage & D3DUSAGE_DYNAMIC) { info->usage = PIPE_USAGE_DYNAMIC; info->bind |= PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE; } if (Usage & D3DUSAGE_SOFTWAREPROCESSING) DBG("Application asked for Software Vertex Processing, " "but this is unimplemented\n"); This->volumes = CALLOC(info->last_level + 1, sizeof(*This->volumes)); if (!This->volumes) return E_OUTOFMEMORY; This->base.pstype = 3; hr = NineBaseTexture9_ctor(&This->base, pParams, NULL, D3DRTYPE_VOLUMETEXTURE, Format, Pool, Usage); if (FAILED(hr)) return hr; voldesc.Format = Format; voldesc.Type = D3DRTYPE_VOLUME; voldesc.Usage = Usage; voldesc.Pool = Pool; for (l = 0; l <= info->last_level; ++l) { voldesc.Width = u_minify(Width, l); voldesc.Height = u_minify(Height, l); voldesc.Depth = u_minify(Depth, l); hr = NineVolume9_new(This->base.base.base.device, NineUnknown(This), This->base.base.resource, l, &voldesc, &This->volumes[l]); if (FAILED(hr)) return hr; } /* Textures start initially dirty */ NineVolumeTexture9_AddDirtyBox(This, NULL); return D3D_OK; }