- fix the texture upload code when RECT is actually used

- optimize FB Locks / Unlocks when RECTs are used
This commit is contained in:
Lionel Ulmer 2003-06-04 23:43:29 +00:00 committed by Alexandre Julliard
parent e14233ae03
commit 068fa5d471
3 changed files with 278 additions and 175 deletions

View File

@ -107,11 +107,11 @@ static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
ENTER_GL();
if (gl_d3d_dev->state == SURFACE_MEMORY_DIRTY) {
d3d_dev->flush_to_framebuffer(d3d_dev, NULL, gl_d3d_dev->lock_surf);
if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
}
gl_d3d_dev->state = SURFACE_GL;
gl_d3d_dev->front_state = SURFACE_GL;
gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
LEAVE_GL();
@ -1103,11 +1103,11 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
EnterCriticalSection(&(This->crit));
ENTER_GL();
if (glThis->state == SURFACE_MEMORY_DIRTY) {
This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
}
glThis->state = SURFACE_GL;
glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
/* Just a hack for now.. Will have to find better algorithm :-/ */
if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
@ -2413,11 +2413,11 @@ static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
/* Clears the screen */
ENTER_GL();
if (glThis->state == SURFACE_MEMORY_DIRTY) {
if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
/* TODO: optimize here the case where Clear changes all the screen... */
This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
}
glThis->state = SURFACE_GL;
glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
if (dwFlags & D3DCLEAR_ZBUFFER) {
bitfield |= GL_DEPTH_BUFFER_BIT;
@ -2700,40 +2700,78 @@ static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, D
{
IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
BOOLEAN is_front;
WINE_GL_BUFFER_TYPE buffer_type;
RECT loc_rect;
if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
is_front = TRUE;
if ((gl_d3d_dev->front_state != SURFACE_GL) &&
(gl_d3d_dev->front_lock_surf != This)) {
buffer_type = WINE_GL_BUFFER_FRONT;
if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
(gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
ERR("Change of front buffer.. Expect graphic corruptions !\n");
}
gl_d3d_dev->front_lock_surf = This;
gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
} else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
is_front = FALSE;
if ((gl_d3d_dev->state != SURFACE_GL) &&
(gl_d3d_dev->lock_surf != This)) {
buffer_type = WINE_GL_BUFFER_BACK;
if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
(gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
ERR("Change of back buffer.. Expect graphic corruptions !\n");
}
gl_d3d_dev->lock_surf = This;
gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
} else {
ERR("Wrong surface type for locking !\n");
return;
}
if (pRect == NULL) {
loc_rect.top = 0;
loc_rect.left = 0;
loc_rect.bottom = This->surface_desc.dwHeight;
loc_rect.right = This->surface_desc.dwWidth;
pRect = &loc_rect;
}
/* Try to acquire the device critical section */
EnterCriticalSection(&(d3d_dev->crit));
if (((is_front == TRUE) && (gl_d3d_dev->front_state == SURFACE_GL)) ||
((is_front == FALSE) && (gl_d3d_dev->state == SURFACE_GL))) {
if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
ERR("Two consecutive locks on %s buffer... Expect problems !\n",
(buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
}
gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
/* Check if the new rectangle is in the previous one or not.
If it is not, flush first the previous locks on screen.
*/
if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
(pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
(pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
(pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
(buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
pRect->left, pRect->top, pRect->right, pRect->bottom,
gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
}
gl_d3d_dev->state[buffer_type] = SURFACE_GL;
gl_d3d_dev->lock_rect[buffer_type] = *pRect;
}
/* In the other case, do not upgrade the locking rectangle as it's no need... */
} else {
gl_d3d_dev->lock_rect[buffer_type] = *pRect;
}
if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
/* If the surface is already in memory, no need to do anything here... */
GLenum buffer_type;
GLenum buffer_format;
GLenum buffer_color;
RECT loc_rect;
int y;
char *dst;
TRACE(" copying frame buffer to main memory.\n");
TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
pRect->left, pRect->top, pRect->right, pRect->bottom);
/* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
may only write to the device... But when we will blit it back to the screen, we need
@ -2746,19 +2784,19 @@ static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, D
(This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
(This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
(This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
buffer_type = GL_UNSIGNED_SHORT_5_6_5;
buffer_format = GL_UNSIGNED_SHORT_5_6_5;
buffer_color = GL_RGB;
} else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
(This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
(This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
(This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
buffer_type = GL_UNSIGNED_BYTE;
buffer_format = GL_UNSIGNED_BYTE;
buffer_color = GL_RGB;
} else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
(This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
(This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
(This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
buffer_type = GL_UNSIGNED_INT_8_8_8_8_REV;
buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
buffer_color = GL_BGRA;
} else {
ERR(" unsupported pixel format at device locking.\n");
@ -2771,39 +2809,25 @@ static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, D
ENTER_GL();
if (is_front == TRUE)
if (buffer_type == WINE_GL_BUFFER_FRONT)
/* Application wants to lock the front buffer */
glReadBuffer(GL_FRONT);
else
/* Application wants to lock the back buffer */
glReadBuffer(GL_BACK);
/* Just a hack while waiting for proper rectangle support */
pRect = NULL;
if (pRect == NULL) {
loc_rect.top = 0;
loc_rect.left = 0;
loc_rect.bottom = This->surface_desc.dwHeight;
loc_rect.right = This->surface_desc.dwWidth;
} else {
loc_rect = *pRect;
}
dst = ((char *)This->surface_desc.lpSurface) +
(loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
(pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
for (y = (This->surface_desc.dwHeight - pRect->top - 1);
y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
y--) {
glReadPixels(loc_rect.left, y,
loc_rect.right - loc_rect.left, 1,
buffer_color, buffer_type, dst);
glReadPixels(pRect->left, y,
pRect->right - pRect->left, 1,
buffer_color, buffer_format, dst);
dst += This->surface_desc.u1.lPitch;
}
if (is_front)
gl_d3d_dev->front_state = SURFACE_MEMORY;
else
gl_d3d_dev->state = SURFACE_MEMORY;
gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
#if 0
/* I keep this code here as it's very useful to debug :-) */
@ -2835,13 +2859,16 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
/* Note : no need here to lock the 'device critical section' as we are already protected by
the GL critical section. */
loc_rect.top = 0;
loc_rect.left = 0;
loc_rect.bottom = surf->surface_desc.dwHeight;
loc_rect.right = surf->surface_desc.dwWidth;
TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
if (pRect == NULL) {
loc_rect.top = 0;
loc_rect.left = 0;
loc_rect.bottom = surf->surface_desc.dwHeight;
loc_rect.right = surf->surface_desc.dwWidth;
pRect = &loc_rect;
}
TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
/* This is a hack to prevent querying the current texture from GL */
gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
@ -2883,8 +2910,8 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
glEnable(GL_SCISSOR_TEST);
glDepthRange(0.0, 1.0);
glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
glScissor(pRect->left, surf->surface_desc.dwHeight - pRect->bottom,
pRect->right - pRect->left, pRect->bottom - pRect->top);
glDisable(GL_LIGHTING);
glDisable(GL_CULL_FACE);
glDisable(GL_ALPHA_TEST);
@ -2893,15 +2920,15 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
glDisable(GL_FOG);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
/* First, upload the texture... */
RECT flush_rect;
flush_rect.left = x;
flush_rect.top = y;
flush_rect.right = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? surf->surface_desc.dwWidth : (x + UNLOCK_TEX_SIZE);
flush_rect.bottom = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? surf->surface_desc.dwHeight : (y + UNLOCK_TEX_SIZE);
flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
@ -2956,21 +2983,28 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
{
BOOLEAN is_front;
WINE_GL_BUFFER_TYPE buffer_type;
IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
is_front = TRUE;
buffer_type = WINE_GL_BUFFER_FRONT;
} else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
is_front = FALSE;
buffer_type = WINE_GL_BUFFER_BACK;
} else {
ERR("Wrong surface type for locking !\n");
return;
}
if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
(buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
}
gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
/* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
if (is_front == TRUE) {
if (buffer_type == WINE_GL_BUFFER_FRONT) {
GLenum prev_draw;
TRACE(" flushing front buffer immediatly on screen.\n");
@ -2978,11 +3012,15 @@ static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
ENTER_GL();
glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
glDrawBuffer(GL_FRONT);
d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
/* Note: we do not use the application provided lock rectangle but our own stored at
lock time. This is because in old D3D versions, the 'lock' parameter did not
exist.
*/
d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
glDrawBuffer(prev_draw);
LEAVE_GL();
} else {
gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
}
}
@ -3156,7 +3194,8 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSur
/* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
LEAVE_GL();
gl_object->state = SURFACE_GL;
gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
/* fill_device_capabilities(d3d->ddraw); */

View File

@ -596,7 +596,8 @@ HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLui
BOOL colorkey_active = need_alpha_ck && (surf_ptr->surface_desc.dwFlags & DDSD_CKSRCBLT);
GLenum internal_format = GL_LUMINANCE; /* A bogus value to be sure to have a nice Mesa warning :-) */
BYTE bpp = GET_BPP(surf_ptr->surface_desc);
BOOL sub_texture = TRUE;
current_surface = surf_ptr;
current_level = level;
@ -606,14 +607,9 @@ HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLui
}
/* Note: we only check width here as you cannot have width non-zero while height is set to zero */
if (tex_width != 0) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
} else {
if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} else {
glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
}
if (tex_width == 0) {
sub_texture = FALSE;
tex_width = surf_ptr->surface_desc.dwWidth;
tex_height = surf_ptr->surface_desc.dwHeight;
}
@ -841,6 +837,17 @@ HRESULT upload_surface_to_tex_memory_init(IDirectDrawSurfaceImpl *surf_ptr, GLui
}
}
if ((sub_texture == TRUE) && (convert_type == NO_CONVERSION)) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
} else {
if (surf_ptr->surface_desc.u1.lPitch == (surf_ptr->surface_desc.dwWidth * bpp)) {
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} else {
glPixelStorei(GL_UNPACK_ROW_LENGTH, surf_ptr->surface_desc.u1.lPitch / bpp);
}
}
return DD_OK;
}
@ -851,7 +858,8 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
RECT lrect;
DWORD width, height;
BYTE bpp = GET_BPP(current_surface->surface_desc);
int line_increase;
if (rect == NULL) {
lrect.top = 0;
lrect.left = 0;
@ -863,11 +871,15 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
width = rect->right - rect->left;
height = rect->bottom - rect->top;
/* Used when converting stuff */
line_increase = src_d->dwWidth - width;
switch (convert_type) {
case CONVERT_PALETTED: {
IDirectDrawPaletteImpl* pal = current_surface->palette;
BYTE table[256][4];
int i;
int x, y;
BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (pal == NULL) {
@ -896,13 +908,16 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
*temp_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
current_tex_width * current_tex_height * sizeof(DWORD));
dst = (BYTE *) *temp_buffer;
for (i = 0; i < height * width; i++) {
BYTE color = *src++;
*dst++ = table[color][0];
*dst++ = table[color][1];
*dst++ = table[color][2];
*dst++ = table[color][3];
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
BYTE color = *src++;
*dst++ = table[color][0];
*dst++ = table[color][1];
*dst++ = table[color][2];
*dst++ = table[color][3];
}
src += line_increase;
}
} break;
@ -917,7 +932,7 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
Note2: when using color-keying + alpha, are the alpha bits part of the
color-space or not ?
*/
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -925,19 +940,22 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(WORD));
dst = (WORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0x0001;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = ((color & 0xFFC0) | ((color & 0x1F) << 1));
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0x0001;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_CK_5551: {
/* Change the alpha value of the color-keyed pixels to emulate color-keying. */
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -945,19 +963,22 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(WORD));
dst = (WORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = color & 0xFFFE;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x0001;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = color & 0xFFFE;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x0001;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_CK_4444: {
/* Change the alpha value of the color-keyed pixels to emulate color-keying. */
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -965,19 +986,22 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(WORD));
dst = (WORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = color & 0xFFF0;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x000F;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = color & 0xFFF0;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x000F;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_CK_4444_ARGB: {
/* Move the four Alpha bits... */
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -985,18 +1009,21 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(WORD));
dst = (WORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = (color & 0x0FFF) << 4;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0xF000) >> 12;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = (color & 0x0FFF) << 4;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0xF000) >> 12;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_CK_1555: {
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -1004,19 +1031,22 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(WORD));
dst = (WORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = (color & 0x7FFF) << 1;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0x8000) >> 15;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = (color & 0x7FFF) << 1;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0x8000) >> 15;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_555: {
/* Converting the 0555 format in 5551 packed */
DWORD i;
int x, y;
WORD *src = (WORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -1025,18 +1055,24 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
dst = (WORD *) *temp_buffer;
if (src_d->dwFlags & DDSD_CKSRCBLT) {
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst = (color & 0x7FFF) << 1;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0x0001;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst = (color & 0x7FFF) << 1;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0x0001;
dst++;
}
src += line_increase;
}
} else {
for (i = 0; i < height * width; i++) {
WORD color = *src++;
*dst++ = ((color & 0x7FFF) << 1) | 0x0001;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
WORD color = *src++;
*dst++ = ((color & 0x7FFF) << 1) | 0x0001;
}
src += line_increase;
}
}
@ -1044,7 +1080,7 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
case CONVERT_CK_RGB24: {
/* This is a pain :-) */
DWORD i;
int x, y;
BYTE *src = (BYTE *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
DWORD *dst;
@ -1053,20 +1089,23 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(DWORD));
dst = (DWORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
DWORD color = *((DWORD *) src) & 0x00FFFFFF;
src += 3;
*dst = *src++ << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0xFF;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
DWORD color = *((DWORD *) src) & 0x00FFFFFF;
src += 3;
*dst = *src++ << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0xFF;
dst++;
}
src += 3 * line_increase;
}
} break;
case CONVERT_CK_8888: {
/* Just use the alpha component to handle color-keying... */
DWORD i;
int x, y;
DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -1074,18 +1113,21 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(DWORD));
dst = (DWORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
DWORD color = *src++;
*dst = color & 0xFFFFFF00;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x000000FF;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
DWORD color = *src++;
*dst = color & 0xFFFFFF00;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= color & 0x000000FF;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_CK_8888_ARGB: {
DWORD i;
int x, y;
DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -1093,19 +1135,22 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
current_tex_width * current_tex_height * sizeof(DWORD));
dst = (DWORD *) *temp_buffer;
for (i = 0; i < height * width; i++) {
DWORD color = *src++;
*dst = (color & 0x00FFFFFF) << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0xFF000000) >> 24;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
DWORD color = *src++;
*dst = (color & 0x00FFFFFF) << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= (color & 0xFF000000) >> 24;
dst++;
}
src += line_increase;
}
} break;
case CONVERT_RGB32_888: {
/* Just add an alpha component and handle color-keying... */
DWORD i;
int x, y;
DWORD *src = (DWORD *) (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top)), *dst;
if (*temp_buffer == NULL)
@ -1114,29 +1159,39 @@ HRESULT upload_surface_to_tex_memory(RECT *rect, DWORD xoffset, DWORD yoffset, v
dst = (DWORD *) *temp_buffer;
if (src_d->dwFlags & DDSD_CKSRCBLT) {
for (i = 0; i < height * width; i++) {
DWORD color = *src++;
*dst = color << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0xFF;
dst++;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
DWORD color = *src++;
*dst = color << 8;
if ((color < src_d->ddckCKSrcBlt.dwColorSpaceLowValue) ||
(color > src_d->ddckCKSrcBlt.dwColorSpaceHighValue))
*dst |= 0xFF;
dst++;
}
src += line_increase;
}
} else {
for (i = 0; i < height * width; i++) {
*dst++ = (*src++ << 8) | 0xFF;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
*dst++ = (*src++ << 8) | 0xFF;
}
src += line_increase;
}
}
} break;
case NO_CONVERSION:
/* Nothing to do here as the name suggests... This just prevents a compiler warning */
/* Nothing to do here as the name suggests... Just set-up the buffer correctly */
surf_buffer = (((BYTE *) src_d->lpSurface) + (bpp * rect->left) + (src_d->u1.lPitch * rect->top));
break;
}
if (convert_type != NO_CONVERSION) {
surf_buffer = *temp_buffer;
if (width != current_tex_width) {
/* Overide the default PixelStore parameter if only using part of the actual texture */
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
}
}
glTexSubImage2D(GL_TEXTURE_2D,

View File

@ -100,6 +100,11 @@ typedef enum {
GL_TRANSFORM_VERTEXBUFFER
} GL_TRANSFORM_STATE;
typedef enum {
WINE_GL_BUFFER_BACK = 0,
WINE_GL_BUFFER_FRONT
} WINE_GL_BUFFER_TYPE;
typedef struct IDirect3DDeviceGLImpl
{
struct IDirect3DDeviceImpl parent;
@ -124,9 +129,13 @@ typedef struct IDirect3DDeviceGLImpl
GLuint unlock_tex;
void *surface_ptr;
GLenum current_internal_format;
SURFACE_STATE state, front_state;
IDirectDrawSurfaceImpl *lock_surf, *front_lock_surf;
/* 0 is back-buffer, 1 is front-buffer */
SURFACE_STATE state[2];
IDirectDrawSurfaceImpl *lock_surf[2];
RECT lock_rect[2];
/* This is just here to print-out a nice warning if we have two successive locks */
BOOLEAN lock_rect_valid[2];
} IDirect3DDeviceGLImpl;
/* This is for the OpenGL additions... */