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) {
+ 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;
}
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");
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)) {
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)
{
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;
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);
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.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 */
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);
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 );
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);
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;
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;
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,
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);
* 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,
return D3DERR_OUTOFVIDEOMEMORY;
}
if (This->zsbuf) {
+ NineSurface9_SetMultiSampleType(This->zsbuf, desc.MultiSampleType);
NineSurface9_SetResourceResize(This->zsbuf, resource);
pipe_resource_reference(&resource, NULL);
} else {