templ.u.tex.last_layer = 0;
templ.u.tex.first_level = 0;
templ.u.tex.last_level = 0;
- templ.swizzle_r = PIPE_SWIZZLE_ZERO;
- templ.swizzle_g = PIPE_SWIZZLE_ZERO;
- templ.swizzle_b = PIPE_SWIZZLE_ZERO;
- templ.swizzle_a = PIPE_SWIZZLE_ONE;
+ templ.swizzle_r = PIPE_SWIZZLE_0;
+ templ.swizzle_g = PIPE_SWIZZLE_0;
+ templ.swizzle_b = PIPE_SWIZZLE_0;
+ templ.swizzle_a = PIPE_SWIZZLE_1;
templ.target = This->dummy_texture->target;
This->dummy_sampler_view = This->pipe->create_sampler_view(This->pipe, This->dummy_texture, &templ);
struct NineBaseTexture9 *dstb = NineBaseTexture9(pDestinationTexture);
struct NineBaseTexture9 *srcb = NineBaseTexture9(pSourceTexture);
unsigned l, m;
- unsigned last_level = dstb->base.info.last_level;
+ unsigned last_src_level, last_dst_level;
RECT rect;
DBG("This=%p pSourceTexture=%p pDestinationTexture=%p\n", This,
pSourceTexture, pDestinationTexture);
+ user_assert(pSourceTexture && pDestinationTexture, D3DERR_INVALIDCALL);
user_assert(pSourceTexture != pDestinationTexture, D3DERR_INVALIDCALL);
user_assert(dstb->base.pool == D3DPOOL_DEFAULT, D3DERR_INVALIDCALL);
user_assert(srcb->base.pool == D3DPOOL_SYSTEMMEM, D3DERR_INVALIDCALL);
-
- if (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) {
- /* Only the first level is updated, the others regenerated. */
- last_level = 0;
- /* if the source has D3DUSAGE_AUTOGENMIPMAP, we have to ignore
- * the sublevels, thus level 0 has to match */
- user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ||
- (srcb->base.info.width0 == dstb->base.info.width0 &&
- srcb->base.info.height0 == dstb->base.info.height0 &&
- srcb->base.info.depth0 == dstb->base.info.depth0),
- D3DERR_INVALIDCALL);
- } else {
- user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP), D3DERR_INVALIDCALL);
- }
-
user_assert(dstb->base.type == srcb->base.type, D3DERR_INVALIDCALL);
+ user_assert(!(srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ||
+ dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP, D3DERR_INVALIDCALL);
+
+ /* Spec: Failure if
+ * . Different formats
+ * . Fewer src levels than dst levels (if the opposite, only matching levels
+ * are supposed to be copied)
+ * . Levels do not match
+ * DDI: Actually the above should pass because of legacy applications
+ * Do what you want about these, but you shouldn't crash.
+ * However driver can expect that the top dimension is greater for src than dst.
+ * Wine tests: Every combination that passes the initial checks should pass.
+ * . Different formats => conversion driver and format dependent.
+ * . 1 level, but size not matching => copy is done (and even crash if src bigger
+ * than dst. For the case where dst bigger, wine doesn't test if a stretch is applied
+ * or if a subrect is copied).
+ * . 8x8 4 sublevels -> 7x7 2 sublevels => driver dependent, On NV seems to be 4x4 subrect
+ * copied to 7x7.
+ *
+ * From these, the proposal is:
+ * . Different formats -> use util_format_translate to translate if possible for surfaces.
+ * Accept ARGB/XRGB for Volumes. Do nothing for the other combinations
+ * . First level copied -> the first level such that src is smaller or equal to dst first level
+ * . number of levels copied -> as long as it fits and textures have levels
+ * That should satisfy the constraints (and instead of crashing for some cases we return D3D_OK)
+ */
- /* Find src level that matches dst level 0: */
- user_assert(srcb->base.info.width0 >= dstb->base.info.width0 &&
- srcb->base.info.height0 >= dstb->base.info.height0 &&
- srcb->base.info.depth0 >= dstb->base.info.depth0,
- D3DERR_INVALIDCALL);
- for (m = 0; m <= srcb->base.info.last_level; ++m) {
+ last_src_level = (srcb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : srcb->base.info.last_level;
+ last_dst_level = (dstb->base.usage & D3DUSAGE_AUTOGENMIPMAP) ? 0 : dstb->base.info.last_level;
+
+ for (m = 0; m <= last_src_level; ++m) {
unsigned w = u_minify(srcb->base.info.width0, m);
unsigned h = u_minify(srcb->base.info.height0, m);
unsigned d = u_minify(srcb->base.info.depth0, m);
- if (w == dstb->base.info.width0 &&
- h == dstb->base.info.height0 &&
- d == dstb->base.info.depth0)
+ if (w <= dstb->base.info.width0 &&
+ h <= dstb->base.info.height0 &&
+ d <= dstb->base.info.depth0)
break;
}
- user_assert(m <= srcb->base.info.last_level, D3DERR_INVALIDCALL);
+ user_assert(m <= last_src_level, D3D_OK);
- last_level = MIN2(last_level, srcb->base.info.last_level - m);
+ last_dst_level = MIN2(srcb->base.info.last_level - m, last_dst_level);
if (dstb->base.type == D3DRTYPE_TEXTURE) {
struct NineTexture9 *dst = NineTexture9(dstb);
for (l = 0; l < m; ++l)
rect_minify_inclusive(&rect);
- for (l = 0; l <= last_level; ++l, ++m) {
+ for (l = 0; l <= last_dst_level; ++l, ++m) {
fit_rect_format_inclusive(dst->base.base.info.format,
&rect,
dst->surfaces[l]->desc.Width,
for (l = 0; l < m; ++l)
rect_minify_inclusive(&rect);
- for (l = 0; l <= last_level; ++l, ++m) {
+ for (l = 0; l <= last_dst_level; ++l, ++m) {
fit_rect_format_inclusive(dst->base.base.info.format,
&rect,
dst->surfaces[l * 6 + z]->desc.Width,
if (src->dirty_box.width == 0)
return D3D_OK;
- for (l = 0; l <= last_level; ++l, ++m)
+ for (l = 0; l <= last_dst_level; ++l, ++m)
NineVolume9_CopyMemToDefault(dst->volumes[l],
src->volumes[m], 0, 0, 0, NULL);
u_box_3d(0, 0, 0, 0, 0, 0, &src->dirty_box);
y = pRect->top;
w = pRect->right - pRect->left;
h = pRect->bottom - pRect->top;
+ /* Wine tests: */
+ if (compressed_format(surf->desc.Format)) {
+ const unsigned bw = util_format_get_blockwidth(surf->base.info.format);
+ const unsigned bh = util_format_get_blockheight(surf->base.info.format);
+
+ user_assert(!(x % bw) && !(y % bh) && !(w % bw) && !(h % bh),
+ D3DERR_INVALIDCALL);
+ }
} else{
x = 0;
y = 0;
for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) {
rt = This->state.rt[i];
if (!rt || rt->desc.Format == D3DFMT_NULL ||
- !(Flags & D3DCLEAR_TARGET))
+ !(bufs & PIPE_CLEAR_COLOR))
continue; /* save space, compiler should hoist this */
cbuf = NineSurface9_GetSurface(rt, sRGB);
for (r = 0; r < Count; ++r) {
x1, y1, x2 - x1, y2 - y1);
}
}
- if (!(Flags & NINED3DCLEAR_DEPTHSTENCIL))
+ if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL))
return D3D_OK;
bufs &= PIPE_CLEAR_DEPTHSTENCIL;
{
const struct nine_state *state = &This->state;
- user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
- user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
+ user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);
+ user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
*pValue = state->ff.tex_stage[Stage][Type];
DBG("Stage=%u Type=%u Value=%08x\n", Stage, Type, Value);
nine_dump_D3DTSS_value(DBG_FF, Type, Value);
- user_assert(Stage < Elements(state->ff.tex_stage), D3DERR_INVALIDCALL);
- user_assert(Type < Elements(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
+ user_assert(Stage < ARRAY_SIZE(state->ff.tex_stage), D3DERR_INVALIDCALL);
+ user_assert(Type < ARRAY_SIZE(state->ff.tex_stage[0]), D3DERR_INVALIDCALL);
state->ff.tex_stage[Stage][Type] = Value;
switch (Type) {
DBG("This=%p pNumPasses=%p\n", This, pNumPasses);
- for (i = 0; i < Elements(state->samp); ++i) {
+ for (i = 0; i < ARRAY_SIZE(state->samp); ++i) {
if (state->samp[i][D3DSAMP_MINFILTER] == D3DTEXF_NONE ||
state->samp[i][D3DSAMP_MAGFILTER] == D3DTEXF_NONE)
return D3DERR_UNSUPPORTEDTEXTUREFILTER;
*/
HRESULT NINE_WINAPI
NineDevice9_GetIndices( struct NineDevice9 *This,
- IDirect3DIndexBuffer9 **ppIndexData /*,
- UINT *pBaseVertexIndex */ )
+ IDirect3DIndexBuffer9 **ppIndexData)
{
user_assert(ppIndexData, D3DERR_INVALIDCALL);
nine_reference_set(ppIndexData, This->state.idxbuf);