GL doesnt like incorrect lengths passed into DXTN processing. This patch should get dxt1 working again, and fixes the regression in Operation Flashpoint
Jason
diff -u3 dlls/d3d8/dx76/device.c dlls/d3d8/device.c --- dlls/d3d8/dx76/device.c 2003-09-18 22:59:22.000000000 +0100 +++ dlls/d3d8/device.c 2003-09-18 22:52:51.000000000 +0100 @@ -625,7 +625,8 @@ volume->myDesc.Pool = Pool; volume->myDesc.Usage = Usage; volume->bytesPerPixel = D3DFmtGetBpp(This, Format); - volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth; + /* Note: Volume textures cannot be dxtn, hence no need to check here */ + volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth; volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size); volume->lockable = TRUE; @@ -779,7 +780,11 @@ object->myDesc.Pool = D3DPOOL_DEFAULT; object->myDesc.MultiSampleType = MultiSample; object->bytesPerPixel = D3DFmtGetBpp(This, Format); - object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + if (Format == D3DFMT_DXT1) { + object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */ + } else { + object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + } object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size); object->lockable = Lockable; object->locked = FALSE; @@ -814,7 +819,11 @@ object->myDesc.Pool = D3DPOOL_DEFAULT; object->myDesc.MultiSampleType = MultiSample; object->bytesPerPixel = D3DFmtGetBpp(This, Format); - object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + if (Format == D3DFMT_DXT1) { + object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */ + } else { + object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + } object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size); object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE; object->locked = FALSE; @@ -844,7 +853,11 @@ object->myDesc.Usage = 0; object->myDesc.Pool = D3DPOOL_SYSTEMMEM; object->bytesPerPixel = D3DFmtGetBpp(This, Format); - object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + if (Format == D3DFMT_DXT1) { + object->myDesc.Size = ((Width * object->bytesPerPixel) * Height) / 2; /* DXT1 is half byte per pixel */ + } else { + object->myDesc.Size = (Width * object->bytesPerPixel) * Height; + } object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size); object->lockable = TRUE; object->locked = FALSE; @@ -921,11 +934,12 @@ int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel; int i; + /* Copy rect by rect */ for (i = 0; i < cRects; i++) { CONST RECT* r = &pSourceRectsArray[i]; CONST POINT* p = &pDestPointsArray[i]; - int copyperline = (r->right - r->left) * bytesPerPixel; + int copyperline; int j; D3DLOCKED_RECT lrSrc; D3DLOCKED_RECT lrDst; @@ -933,7 +947,11 @@ TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y); - + if (src->myDesc.Format == D3DFMT_DXT1) { + copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */ + } else { + copyperline = ((r->right - r->left) * bytesPerPixel); + } IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY); dest_rect.left = p->x; dest_rect.top = p->y; @@ -943,15 +961,6 @@ TRACE("Locked src and dst\n"); /* Find where to start */ -#if 0 - from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel); - to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel); - /* Copy line by line */ - for (j = 0; j < (r->bottom - r->top); j++) { - memcpy(to + (j * pitchTo), from + (j * pitchFrom), copyperline); - } -#endif - for (j = 0; j < (r->bottom - r->top); j++) { memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline); } @@ -1074,17 +1083,6 @@ ENTER_GL(); - /* - { - IDirect3DSurface8Impl* tmp = ((IDirect3DSurface8Impl*) pDestSurface); - FIXME("dest:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel); - FIXME("dest2:pitch%u\n", lockedRect.Pitch); - FIXME("src:%u,%u\n", This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight); - tmp = This->frontBuffer; - FIXME("src2:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel); - } - */ - glFlush(); vcheckGLcall("glFlush"); glGetIntegerv(GL_READ_BUFFER, &prev_read); @@ -1206,6 +1204,10 @@ { long j; long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel; + + if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */ + pitch = pitch / 2; + for (j = 0; j < This->renderTarget->myDesc.Height; ++j) { glReadPixels(0, This->renderTarget->myDesc.Height - j - 1, @@ -4025,6 +4027,10 @@ { long j; long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel; + + if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */ + pitch = pitch / 2; + for (j = 0; j < This->renderTarget->myDesc.Height; ++j) { glReadPixels(0, This->renderTarget->myDesc.Height - j - 1, diff -u3 dlls/d3d8/dx76/directx.c dlls/d3d8/directx.c --- dlls/d3d8/dx76/directx.c 2003-09-18 21:14:23.000000000 +0100 +++ dlls/d3d8/directx.c 2003-09-18 21:42:21.000000000 +0100 @@ -786,9 +786,11 @@ } else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) { FIXME(" FOUND: EXT Secondary coord support\n"); This->gl_info.supported[EXT_SECONDARY_COLOR] = TRUE; +#if defined(GL_EXT_texture_compression_s3tc) } else if (strcmp(ThisExtn, "GL_EXT_texture_compression_s3tc") == 0) { FIXME(" FOUND: EXT Texture S3TC compression support\n"); This->gl_info.supported[EXT_TEXTURE_COMPRESSION_S3TC] = TRUE; +#endif } else if (strcmp(ThisExtn, "GL_EXT_texture_env_dot3") == 0) { if (FALSE == This->gl_info.supported[ARB_TEXTURE_ENV_DOT3]) { FIXME(" FOUND: EXT Dot3 support\n"); diff -u3 dlls/d3d8/dx76/surface.c dlls/d3d8/surface.c --- dlls/d3d8/dx76/surface.c 2003-09-18 22:59:26.000000000 +0100 +++ dlls/d3d8/surface.c 2003-09-18 22:55:07.000000000 +0100 @@ -153,6 +153,8 @@ } pLockedRect->Pitch = This->bytesPerPixel * This->myDesc.Width; /* Bytes / row */ + if (This->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */ + pLockedRect->Pitch = pLockedRect->Pitch/2; if (NULL == pRect) { pLockedRect->pBits = This->allocatedMemory; @@ -163,7 +165,12 @@ TRACE("Locked Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom); } else { TRACE("Lock Rect (%p) = l %ld, t %ld, r %ld, b %ld\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom); - pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel); + + if (This->myDesc.Format == D3DFMT_DXT1) { /* DXT1 is half byte per pixel */ + pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel/2)); + } else { + pLockedRect->pBits = This->allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel); + } This->lockedRect.left = pRect->left; This->lockedRect.top = pRect->top; This->lockedRect.right = pRect->right; @@ -491,6 +498,8 @@ LEAVE_GL(); } +#else + FIXME("Using DXT1/3/5 without advertized support\n"); #endif } else { TRACE("Calling glTexImage2D %x i=%d, intfmt=%x, w=%d, h=%d,0=%d, glFmt=%x, glType=%x, Mem=%p\n", diff -u3 dlls/d3d8/dx76/utils.c dlls/d3d8/utils.c --- dlls/d3d8/dx76/utils.c 2003-09-18 22:59:27.000000000 +0100 +++ dlls/d3d8/utils.c 2003-09-18 22:29:48.000000000 +0100 @@ -394,6 +394,11 @@ case D3DFMT_D24S8: retVal = 4; break; case D3DFMT_D24X8: retVal = 4; break; case D3DFMT_D32: retVal = 4; break; + /* Compressed */ + case D3DFMT_DXT1: retVal = 1; break; /* Actually 8 bytes per 16 pixels - Special cased later */ + case D3DFMT_DXT3: retVal = 1; break; /* Actually 16 bytes per 16 pixels */ + case D3DFMT_DXT5: retVal = 1; break; /* Actually 16 bytes per 16 pixels */ + /* unknown */ case D3DFMT_UNKNOWN: /* Guess at the highest value of the above */ @@ -424,6 +429,7 @@ } } #endif + if (retVal == 0) { switch (fmt) { case D3DFMT_P8: retVal = GL_COLOR_INDEX8_EXT; break; @@ -445,22 +451,8 @@ } GLenum D3DFmt2GLFmt(IDirect3DDevice8Impl* This, D3DFORMAT fmt) { - GLenum retVal; + GLenum retVal = 0; - switch (fmt) { - case D3DFMT_P8: retVal = GL_COLOR_INDEX; break; - case D3DFMT_A8P8: retVal = GL_COLOR_INDEX; break; - - case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break; - case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break; - case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break; - case D3DFMT_R8G8B8: retVal = GL_BGR; break; - case D3DFMT_R5G6B5: retVal = GL_RGB; break; - case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break; - default: - FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt)); - retVal = GL_BGR; - } #if defined(GL_EXT_texture_compression_s3tc) if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { switch (fmt) { @@ -473,27 +465,31 @@ } } #endif + + if (retVal == 0) { + switch (fmt) { + case D3DFMT_P8: retVal = GL_COLOR_INDEX; break; + case D3DFMT_A8P8: retVal = GL_COLOR_INDEX; break; + + case D3DFMT_A4R4G4B4: retVal = GL_BGRA; break; + case D3DFMT_A8R8G8B8: retVal = GL_BGRA; break; + case D3DFMT_X8R8G8B8: retVal = GL_BGRA; break; + case D3DFMT_R8G8B8: retVal = GL_BGR; break; + case D3DFMT_R5G6B5: retVal = GL_RGB; break; + case D3DFMT_A1R5G5B5: retVal = GL_BGRA; break; + default: + FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt)); + retVal = GL_BGR; + } + } + TRACE("fmt2glFmt for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal); return retVal; } GLenum D3DFmt2GLType(IDirect3DDevice8Impl* This, D3DFORMAT fmt) { - GLenum retVal; + GLenum retVal = 0; - switch (fmt) { - case D3DFMT_P8: retVal = GL_UNSIGNED_BYTE; break; - case D3DFMT_A8P8: retVal = GL_UNSIGNED_BYTE; break; - - case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break; - case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break; - case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break; - case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5; break; - case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break; - case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; - default: - FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt)); - retVal = GL_UNSIGNED_BYTE; - } #if defined(GL_EXT_texture_compression_s3tc) if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { switch (fmt) { @@ -506,6 +502,24 @@ } } #endif + + if (retVal == 0) { + switch (fmt) { + case D3DFMT_P8: retVal = GL_UNSIGNED_BYTE; break; + case D3DFMT_A8P8: retVal = GL_UNSIGNED_BYTE; break; + + case D3DFMT_A4R4G4B4: retVal = GL_UNSIGNED_SHORT_4_4_4_4_REV; break; + case D3DFMT_A8R8G8B8: retVal = GL_UNSIGNED_BYTE; break; + case D3DFMT_X8R8G8B8: retVal = GL_UNSIGNED_BYTE; break; + case D3DFMT_R5G6B5: retVal = GL_UNSIGNED_SHORT_5_6_5; break; + case D3DFMT_R8G8B8: retVal = GL_UNSIGNED_BYTE; break; + case D3DFMT_A1R5G5B5: retVal = GL_UNSIGNED_SHORT_1_5_5_5_REV; break; + default: + FIXME("Unhandled fmt(%u,%s)\n", fmt, debug_d3dformat(fmt)); + retVal = GL_UNSIGNED_BYTE; + } + } + TRACE("fmt2glType for fmt(%u,%s) = %x\n", fmt, debug_d3dformat(fmt), retVal); return retVal; }