summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/state_trackers/nine/adapter9.c20
-rw-r--r--src/gallium/state_trackers/nine/device9.c8
-rw-r--r--src/gallium/state_trackers/nine/nine_pipe.h55
-rw-r--r--src/gallium/state_trackers/nine/nine_state.c6
-rw-r--r--src/gallium/state_trackers/nine/surface9.c17
-rw-r--r--src/gallium/state_trackers/nine/surface9.h7
-rw-r--r--src/gallium/state_trackers/nine/swapchain9.c24
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 fbbc586..09bfa39 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 50565b8..47fd3a4 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 bbb148d..df3b382 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 66c7581..ed3c821 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 ffa8c2a..dc31bb9 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 a83e8dd..476bc81 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 fcda9c7..86c9be6 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 {