X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fnine%2Fsurface9.c;h=db74de2823acd0fe640b70a9903b849b2a9e0128;hb=9e467d111b2c9046c9b35b9e76891a8cfbb752c1;hp=26c2d69d276ab0725a99db2440247cf0e397d385;hpb=7089d88199d607d8a135a9605f14ec6393134205;p=mesa.git diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c index 26c2d69d276..db74de2823a 100644 --- a/src/gallium/state_trackers/nine/surface9.c +++ b/src/gallium/state_trackers/nine/surface9.c @@ -20,6 +20,7 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include "iunknown.h" #include "surface9.h" #include "device9.h" @@ -43,6 +44,9 @@ #define DBG_CHANNEL DBG_SURFACE +static void +NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ); + HRESULT NineSurface9_ctor( struct NineSurface9 *This, struct NineUnknownParams *pParams, @@ -100,12 +104,15 @@ NineSurface9_ctor( struct NineSurface9 *This, This->base.info.last_level = 0; This->base.info.array_size = 1; This->base.info.nr_samples = multisample_type; + This->base.info.nr_storage_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) { + if (!depth_stencil_format(pDesc->Format)) + return D3DERR_INVALIDCALL; This->base.info.bind = d3d9_get_pipe_depth_format_bindings(pDesc->Format); if (TextureType) This->base.info.bind |= PIPE_BIND_SAMPLER_VIEW; @@ -132,22 +139,26 @@ NineSurface9_ctor( struct NineSurface9 *This, } /* Get true format */ - This->format_conversion = d3d9_to_pipe_format_checked(This->base.info.screen, + This->format_internal = 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, + if (This->base.info.format != This->format_internal || + /* DYNAMIC Textures requires same stride as ram buffers. + * Do not use workaround by default as it eats more virtual space */ + (pParams->device->workarounds.dynamic_texture_workaround && + pDesc->Pool == D3DPOOL_DEFAULT && pDesc->Usage & D3DUSAGE_DYNAMIC)) { + This->data_internal = align_calloc( + nine_format_get_level_alloc_size(This->format_internal, pDesc->Width, pDesc->Height, 0), 32); - if (!This->data_conversion) + if (!This->data_internal) return E_OUTOFMEMORY; - This->stride_conversion = nine_format_get_stride(This->format_conversion, + This->stride_internal = nine_format_get_stride(This->format_internal, pDesc->Width); } @@ -183,10 +194,8 @@ NineSurface9_ctor( struct NineSurface9 *This, if (This->base.resource && (pDesc->Usage & D3DUSAGE_DYNAMIC)) This->base.resource->flags |= NINE_RESOURCE_FLAG_LOCKABLE; - if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) { - (void) NineSurface9_CreatePipeSurface(This, 0); - (void) NineSurface9_CreatePipeSurface(This, 1); - } + if (This->base.resource && (pDesc->Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))) + NineSurface9_CreatePipeSurfaces(This); /* TODO: investigate what else exactly needs to be cleared */ if (This->base.resource && (pDesc->Usage & D3DUSAGE_RENDERTARGET)) @@ -202,9 +211,15 @@ NineSurface9_dtor( struct NineSurface9 *This ) { DBG("This=%p\n", This); - if (This->transfer) - NineSurface9_UnlockRect(This); + if (This->transfer) { + struct pipe_context *pipe = nine_context_get_pipe_multithread(This->base.base.device); + pipe->transfer_unmap(pipe, This->transfer); + This->transfer = NULL; + } + /* Note: Following condition cannot happen currently, since we + * refcount the surface in the functions increasing + * pending_uploads_counter. */ if (p_atomic_read(&This->pending_uploads_counter)) nine_csmt_process(This->base.base.device); @@ -214,13 +229,13 @@ NineSurface9_dtor( struct NineSurface9 *This ) /* Release system memory when we have to manage it (no parent) */ if (!This->base.base.container && This->data) align_free(This->data); - if (This->data_conversion) - align_free(This->data_conversion); + if (This->data_internal) + align_free(This->data_internal); NineResource9_dtor(&This->base); } -struct pipe_surface * -NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB ) +static void +NineSurface9_CreatePipeSurfaces( struct NineSurface9 *This ) { struct pipe_context *pipe; struct pipe_screen *screen = NineDevice9_GetScreen(This->base.base.device); @@ -232,24 +247,36 @@ NineSurface9_CreatePipeSurface( struct NineSurface9 *This, const int sRGB ) assert(resource); srgb_format = util_format_srgb(resource->format); - if (sRGB && srgb_format != PIPE_FORMAT_NONE && - screen->is_format_supported(screen, srgb_format, - resource->target, 0, resource->bind)) - templ.format = srgb_format; - else - templ.format = resource->format; + if (srgb_format == PIPE_FORMAT_NONE || + !screen->is_format_supported(screen, srgb_format, + resource->target, 0, 0, resource->bind)) + srgb_format = resource->format; + + memset(&templ, 0, sizeof(templ)); + templ.format = resource->format; templ.u.tex.level = This->level; templ.u.tex.first_layer = This->layer; templ.u.tex.last_layer = This->layer; pipe = nine_context_get_pipe_acquire(This->base.base.device); - This->surface[sRGB] = pipe->create_surface(pipe, resource, &templ); + + This->surface[0] = pipe->create_surface(pipe, resource, &templ); + + memset(&templ, 0, sizeof(templ)); + templ.format = srgb_format; + templ.u.tex.level = This->level; + templ.u.tex.first_layer = This->layer; + templ.u.tex.last_layer = This->layer; + + This->surface[1] = pipe->create_surface(pipe, resource, &templ); + nine_context_get_pipe_release(This->base.base.device); - assert(This->surface[sRGB]); - return This->surface[sRGB]; + + assert(This->surface[0]); /* TODO: Handle failure */ + assert(This->surface[1]); } -#ifdef DEBUG +#if defined(DEBUG) || !defined(NDEBUG) void NineSurface9_Dump( struct NineSurface9 *This ) { @@ -277,7 +304,7 @@ NineSurface9_Dump( struct NineSurface9 *This ) NineUnknown_Release(NineUnknown(tex)); } } -#endif /* DEBUG */ +#endif /* DEBUG || !NDEBUG */ HRESULT NINE_WINAPI NineSurface9_GetContainer( struct NineSurface9 *This, @@ -371,15 +398,15 @@ NineSurface9_AddDirtyRect( struct NineSurface9 *This, } } -static inline uint8_t * -NineSurface9_GetSystemMemPointer(struct NineSurface9 *This, int x, int y) +static inline unsigned +NineSurface9_GetSystemMemOffset(enum pipe_format format, unsigned stride, + int x, int y) { - unsigned x_offset = util_format_get_stride(This->base.info.format, x); + unsigned x_offset = util_format_get_stride(format, x); - y = util_format_get_nblocksy(This->base.info.format, y); + y = util_format_get_nblocksy(format, y); - assert(This->data); - return This->data + (y * This->stride + x_offset); + return y * stride + x_offset; } HRESULT NINE_WINAPI @@ -458,34 +485,48 @@ NineSurface9_LockRect( struct NineSurface9 *This, if (p_atomic_read(&This->pending_uploads_counter)) nine_csmt_process(This->base.base.device); - if (This->data_conversion) { - /* For now we only have uncompressed formats here */ - pLockedRect->Pitch = This->stride_conversion; - pLockedRect->pBits = This->data_conversion + box.y * This->stride_conversion + - util_format_get_stride(This->format_conversion, box.x); - } else if (This->data) { + if (This->data_internal || This->data) { + enum pipe_format format = This->base.info.format; + unsigned stride = This->stride; + uint8_t *data = This->data; + if (This->data_internal) { + format = This->format_internal; + stride = This->stride_internal; + data = This->data_internal; + } DBG("returning system memory\n"); /* ATI1 and ATI2 need special handling, because of d3d9 bug. * We must advertise to the application as if it is uncompressed * and bpp 8, and the app has a workaround to work with the fact * that it is actually compressed. */ - if (is_ATI1_ATI2(This->base.info.format)) { + if (is_ATI1_ATI2(format)) { pLockedRect->Pitch = This->desc.Width; - pLockedRect->pBits = This->data + box.y * This->desc.Width + box.x; + pLockedRect->pBits = data + box.y * This->desc.Width + box.x; } else { - pLockedRect->Pitch = This->stride; - pLockedRect->pBits = NineSurface9_GetSystemMemPointer(This, - box.x, - box.y); + pLockedRect->Pitch = stride; + pLockedRect->pBits = data + + NineSurface9_GetSystemMemOffset(format, + stride, + box.x, + box.y); } } else { + bool no_refs = !p_atomic_read(&This->base.base.bind) && + !(This->base.base.container && p_atomic_read(&This->base.base.container->bind)); DBG("mapping pipe_resource %p (level=%u usage=%x)\n", resource, This->level, usage); - pipe = NineDevice9_GetPipe(This->base.base.device); + /* if the object is not bound internally, there can't be any pending + * operation with the surface in the queue */ + if (no_refs) + pipe = nine_context_get_pipe_acquire(This->base.base.device); + else + pipe = NineDevice9_GetPipe(This->base.base.device); pLockedRect->pBits = pipe->transfer_map(pipe, resource, This->level, usage, &box, &This->transfer); + if (no_refs) + nine_context_get_pipe_release(This->base.base.device); if (!This->transfer) { DBG("transfer_map failed\n"); if (Flags & D3DLOCK_DONOTWAIT) @@ -507,6 +548,7 @@ NineSurface9_LockRect( struct NineSurface9 *This, HRESULT NINE_WINAPI NineSurface9_UnlockRect( struct NineSurface9 *This ) { + struct pipe_box dst_box, src_box; struct pipe_context *pipe; DBG("This=%p lock_count=%u\n", This, This->lock_count); user_assert(This->lock_count, D3DERR_INVALIDCALL); @@ -518,36 +560,34 @@ NineSurface9_UnlockRect( struct NineSurface9 *This ) } --This->lock_count; - if (This->data_conversion) { - struct pipe_transfer *transfer; - uint8_t *dst = This->data; - struct pipe_box box; - - u_box_origin_2d(This->desc.Width, This->desc.Height, &box); - - pipe = NineDevice9_GetPipe(This->base.base.device); - if (!dst) { - dst = pipe->transfer_map(pipe, - This->base.resource, - This->level, - PIPE_TRANSFER_WRITE | - PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE, - &box, &transfer); - if (!dst) - return D3D_OK; + if (This->data_internal) { + if (This->data) { + (void) util_format_translate(This->base.info.format, + This->data, This->stride, + 0, 0, + This->format_internal, + This->data_internal, + This->stride_internal, + 0, 0, + This->desc.Width, This->desc.Height); + } else { + u_box_2d_zslice(0, 0, This->layer, + This->desc.Width, This->desc.Height, &dst_box); + u_box_2d_zslice(0, 0, 0, + This->desc.Width, This->desc.Height, &src_box); + + nine_context_box_upload(This->base.base.device, + &This->pending_uploads_counter, + (struct NineUnknown *)This, + This->base.resource, + This->level, + &dst_box, + This->format_internal, + This->data_internal, + This->stride_internal, + 0, /* depth = 1 */ + &src_box); } - - (void) util_format_translate(This->base.info.format, - dst, This->data ? This->stride : transfer->stride, - 0, 0, - This->format_conversion, - This->data_conversion, - This->stride_conversion, - 0, 0, - This->desc.Width, This->desc.Height); - - if (!This->data) - pipe_transfer_unmap(pipe, transfer); } return D3D_OK; } @@ -628,7 +668,7 @@ NineSurface9_CopyMemToDefault( struct NineSurface9 *This, nine_context_box_upload(This->base.base.device, &From->pending_uploads_counter, - (struct NineUnknown *)This, + (struct NineUnknown *)From, r_dst, This->level, &dst_box, @@ -636,11 +676,24 @@ NineSurface9_CopyMemToDefault( struct NineSurface9 *This, From->data, From->stride, 0, /* depth = 1 */ &src_box); + if (From->texture == D3DRTYPE_TEXTURE) { + struct NineTexture9 *tex = + NineTexture9(From->base.base.container); + /* D3DPOOL_SYSTEMMEM with buffer content passed + * from the user: execute the upload right now. + * It is possible it is enough to delay upload + * until the surface refcount is 0, but the + * bind refcount may not be 0, and thus the dtor + * is not executed (and doesn't trigger the + * pending_uploads_counter check). */ + if (!tex->managed_buffer) + nine_csmt_process(This->base.base.device); + } - if (This->data_conversion) - (void) util_format_translate(This->format_conversion, - This->data_conversion, - This->stride_conversion, + if (This->data_internal) + (void) util_format_translate(This->format_internal, + This->data_internal, + This->stride_internal, dst_x, dst_y, From->base.info.format, From->data, From->stride, @@ -677,7 +730,7 @@ NineSurface9_CopyDefaultToMem( struct NineSurface9 *This, p_src = pipe->transfer_map(pipe, r_src, From->level, PIPE_TRANSFER_READ, &src_box, &transfer); - p_dst = NineSurface9_GetSystemMemPointer(This, 0, 0); + p_dst = This->data; assert (p_src && p_dst); @@ -732,6 +785,33 @@ NineSurface9_UploadSelf( struct NineSurface9 *This, return D3D_OK; } +/* Currently nine_context uses the NineSurface9 + * fields when it is render target. Any modification requires + * pending commands with the surface to be executed. If the bind + * count is 0, there is no pending commands. */ +#define PROCESS_IF_BOUND(surf) \ + if (surf->base.base.bind) \ + nine_csmt_process(surf->base.base.device); + +void +NineSurface9_SetResource( struct NineSurface9 *This, + struct pipe_resource *resource, unsigned level ) +{ + /* No need to call PROCESS_IF_BOUND, because SetResource is used only + * for MANAGED textures, and they are not render targets. */ + assert(This->base.pool == D3DPOOL_MANAGED); + This->level = level; + pipe_resource_reference(&This->base.resource, resource); +} + +void +NineSurface9_SetMultiSampleType( struct NineSurface9 *This, + D3DMULTISAMPLE_TYPE mst ) +{ + PROCESS_IF_BOUND(This); + This->desc.MultiSampleType = mst; +} + void NineSurface9_SetResourceResize( struct NineSurface9 *This, struct pipe_resource *resource ) @@ -741,21 +821,21 @@ NineSurface9_SetResourceResize( struct NineSurface9 *This, assert(This->desc.Pool == D3DPOOL_DEFAULT); assert(!This->texture); + PROCESS_IF_BOUND(This); pipe_resource_reference(&This->base.resource, resource); This->desc.Width = This->base.info.width0 = resource->width0; This->desc.Height = This->base.info.height0 = resource->height0; This->base.info.nr_samples = resource->nr_samples; + This->base.info.nr_storage_samples = resource->nr_storage_samples; This->stride = nine_format_get_stride(This->base.info.format, This->desc.Width); pipe_surface_reference(&This->surface[0], NULL); pipe_surface_reference(&This->surface[1], NULL); - if (resource) { - (void) NineSurface9_CreatePipeSurface(This, 0); - (void) NineSurface9_CreatePipeSurface(This, 1); - } + if (resource) + NineSurface9_CreatePipeSurfaces(This); }