diff options
-rw-r--r-- | src/gallium/state_trackers/nine/adapter9.c | 20 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/device9.c | 8 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_pipe.h | 55 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/nine_state.c | 6 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/surface9.c | 17 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/surface9.h | 7 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/swapchain9.c | 24 |
7 files changed, 125 insertions, 12 deletions
diff --git a/src/gallium/state_trackers/nine/adapter9.c b/src/gallium/state_trackers/nine/adapter9.c index fbbc586204a..09bfa3989ff 100644 --- a/src/gallium/state_trackers/nine/adapter9.c +++ b/src/gallium/state_trackers/nine/adapter9.c @@ -401,16 +401,30 @@ NineAdapter9_CheckDeviceMultiSampleType( struct NineAdapter9 *This, 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) { + 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) - *pQualityLevels = 1; /* gallium doesn't have quality levels */ + 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; } diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index 50565b876dd..47fd3a48b55 100644 --- a/src/gallium/state_trackers/nine/device9.c +++ b/src/gallium/state_trackers/nine/device9.c @@ -1653,7 +1653,8 @@ NineDevice9_StretchRect( struct NineDevice9 *This, clamped = !!xy; } - ms = (dst->desc.MultiSampleType | 1) != (src->desc.MultiSampleType | 1); + ms = (dst->desc.MultiSampleType != src->desc.MultiSampleType) || + (dst->desc.MultiSampleQuality != src->desc.MultiSampleQuality); if (clamped || scaled || (blit.dst.format != blit.src.format) || ms) { DBG("using pipe->blit()\n"); @@ -1826,6 +1827,11 @@ NineDevice9_SetRenderTarget( struct NineDevice9 *This, This->state.scissor.maxy = rt->desc.Height; This->state.changed.group |= NINE_STATE_VIEWPORT | NINE_STATE_SCISSOR | NINE_STATE_MULTISAMPLE; + + if (This->state.rt[0] && + (This->state.rt[0]->desc.MultiSampleType == D3DMULTISAMPLE_NONMASKABLE) != + (rt->desc.MultiSampleType == D3DMULTISAMPLE_NONMASKABLE)) + This->state.changed.group |= NINE_STATE_SAMPLE_MASK; } if (This->state.rt[i] != NineSurface9(pRenderTarget)) { diff --git a/src/gallium/state_trackers/nine/nine_pipe.h b/src/gallium/state_trackers/nine/nine_pipe.h index bbb148db66c..df3b38245c0 100644 --- a/src/gallium/state_trackers/nine/nine_pipe.h +++ b/src/gallium/state_trackers/nine/nine_pipe.h @@ -348,6 +348,61 @@ d3d9_to_pipe_format_checked(struct pipe_screen *screen, return PIPE_FORMAT_NONE; } +/* The quality levels are vendor dependent, so we set our own. + * Every quality level has its own sample count and sample + * position matrix. + * The exact mapping might differ from system to system but thats OK, + * as there's no way to gather more information about quality levels + * in D3D9. + * In case of NONMASKABLE multisample map every quality-level + * to a MASKABLE MultiSampleType: + * 0: no MSAA + * 1: 2x MSAA + * 2: 4x MSAA + * ... + * If the requested quality level is not available to nearest + * matching quality level is used. + * If no multisample is available the function sets + * multisample to D3DMULTISAMPLE_NONE and returns zero. + */ +static inline HRESULT +d3dmultisample_type_check(struct pipe_screen *screen, + D3DFORMAT format, + D3DMULTISAMPLE_TYPE *multisample, + DWORD multisamplequality, + DWORD *levels) +{ + unsigned bind, i; + + assert(multisample); + + if (levels) + *levels = 1; + + if (*multisample == D3DMULTISAMPLE_NONMASKABLE) { + if (depth_stencil_format(format)) + bind = d3d9_get_pipe_depth_format_bindings(format); + else /* render-target */ + bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + + *multisample = 0; + for (i = D3DMULTISAMPLE_2_SAMPLES; i < D3DMULTISAMPLE_16_SAMPLES && + multisamplequality; ++i) { + if (d3d9_to_pipe_format_checked(screen, format, PIPE_TEXTURE_2D, + i, bind, FALSE, FALSE) != PIPE_FORMAT_NONE) { + multisamplequality--; + if (levels) + (*levels)++; + *multisample = i; + } + } + } + /* Make sure to get an exact match */ + if (multisamplequality) + return D3DERR_INVALIDCALL; + return D3D_OK; +} + static inline const char * d3dformat_to_string(D3DFORMAT fmt) { diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index 66c75812c15..ed3c821f337 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -1088,7 +1088,11 @@ nine_update_state(struct NineDevice9 *device) pipe->set_blend_color(pipe, &color); } if (group & NINE_STATE_SAMPLE_MASK) { - pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]); + if (state->rt[0]->desc.MultiSampleType == D3DMULTISAMPLE_NONMASKABLE) { + pipe->set_sample_mask(pipe, ~0); + } else { + pipe->set_sample_mask(pipe, state->rs[D3DRS_MULTISAMPLEMASK]); + } } if (group & NINE_STATE_STENCIL_REF) { struct pipe_stencil_ref ref; diff --git a/src/gallium/state_trackers/nine/surface9.c b/src/gallium/state_trackers/nine/surface9.c index ffa8c2af1bd..dc31bb93786 100644 --- a/src/gallium/state_trackers/nine/surface9.c +++ b/src/gallium/state_trackers/nine/surface9.c @@ -58,6 +58,7 @@ NineSurface9_ctor( struct NineSurface9 *This, 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); @@ -82,6 +83,18 @@ NineSurface9_ctor( struct NineSurface9 *This, 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 */ @@ -92,7 +105,7 @@ NineSurface9_ctor( struct NineSurface9 *This, This->base.info.depth0 = 1; This->base.info.last_level = 0; This->base.info.array_size = 1; - This->base.info.nr_samples = pDesc->MultiSampleType; + This->base.info.nr_samples = multisample_type; This->base.info.usage = PIPE_USAGE_DEFAULT; This->base.info.bind = PIPE_BIND_SAMPLER_VIEW; /* StretchRect */ @@ -721,7 +734,7 @@ NineSurface9_SetResourceResize( struct NineSurface9 *This, This->desc.Width = This->base.info.width0 = resource->width0; This->desc.Height = This->base.info.height0 = resource->height0; - This->desc.MultiSampleType = This->base.info.nr_samples = resource->nr_samples; + This->base.info.nr_samples = resource->nr_samples; This->stride = nine_format_get_stride(This->base.info.format, This->desc.Width); diff --git a/src/gallium/state_trackers/nine/surface9.h b/src/gallium/state_trackers/nine/surface9.h index a83e8dd4c71..476bc81557a 100644 --- a/src/gallium/state_trackers/nine/surface9.h +++ b/src/gallium/state_trackers/nine/surface9.h @@ -116,6 +116,13 @@ NineSurface9_SetResource( struct NineSurface9 *This, pipe_surface_reference(&This->surface[1], NULL); } +static inline void +NineSurface9_SetMultiSampleType( struct NineSurface9 *This, + D3DMULTISAMPLE_TYPE mst ) +{ + This->desc.MultiSampleType = mst; +} + void NineSurface9_SetResourceResize( struct NineSurface9 *This, struct pipe_resource *resource ); diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c index fcda9c7837e..86c9be66ae6 100644 --- a/src/gallium/state_trackers/nine/swapchain9.c +++ b/src/gallium/state_trackers/nine/swapchain9.c @@ -120,6 +120,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, 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); @@ -204,15 +205,26 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, newBufferCount = pParams->BackBufferCount + (pParams->SwapEffect != D3DSWAPEFFECT_COPY); + 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, pParams->MultiSampleType, + 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 || - pParams->MultiSampleType >= 2 || + multisample_type >= 2 || (This->actx->ref && This->actx->ref == This->screen)) has_present_buffers = TRUE; @@ -239,7 +251,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, desc.Type = D3DRTYPE_SURFACE; desc.Pool = D3DPOOL_DEFAULT; desc.MultiSampleType = pParams->MultiSampleType; - desc.MultiSampleQuality = 0; + desc.MultiSampleQuality = pParams->MultiSampleQuality; desc.Width = pParams->BackBufferWidth; desc.Height = pParams->BackBufferHeight; @@ -279,7 +291,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, for (i = 0; i < newBufferCount; ++i) { tmplt.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; - tmplt.nr_samples = pParams->MultiSampleType; + tmplt.nr_samples = multisample_type; if (!has_present_buffers) tmplt.bind |= NINE_BIND_PRESENTBUFFER_FLAGS; tmplt.format = d3d9_to_pipe_format_checked(This->screen, @@ -297,6 +309,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, 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); @@ -336,7 +349,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, * If it fails with PIPE_BIND_SAMPLER_VIEW, then the app check for texture support * would fail too, so we are fine. */ tmplt.bind |= PIPE_BIND_SAMPLER_VIEW; - tmplt.nr_samples = pParams->MultiSampleType; + tmplt.nr_samples = multisample_type; tmplt.format = d3d9_to_pipe_format_checked(This->screen, pParams->AutoDepthStencilFormat, PIPE_TEXTURE_2D, @@ -362,6 +375,7 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, return D3DERR_OUTOFVIDEOMEMORY; } if (This->zsbuf) { + NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType); NineSurface9_SetResourceResize(This->zsbuf, resource); pipe_resource_reference(&resource, NULL); } else { |