Yet another D3D patch....
Lionel Ulmer
lionel.ulmer at free.fr
Fri Nov 29 16:16:30 CST 2002
Hi all,
This patch should not be dependant of any others... But to prevent line
number errors, better to commit it after the 5 -> 9 series (yeah, the
attachements are numbered to ease tracking :-) ).
Changelog:
- start of support for device locking / unlocking via glReadPixels /
glDrawPixels interface (slow but should be enough for a start)
- implement one vertex case for the D3D3/7 DrawPrimitive functions
- fix a missing \n in a TRACE call
Lionel
--
Lionel Ulmer - http://www.bbrox.org/
-------------- next part --------------
--- ../wine_work_base/dlls/ddraw/d3dviewport.c Sat Nov 23 20:45:28 2002
+++ dlls/ddraw/d3dviewport.c Fri Nov 29 21:52:36 2002
@@ -438,7 +438,7 @@
((dwColor >> 8) & 0xFF) / 255.0,
((dwColor >> 0) & 0xFF) / 255.0,
((dwColor >> 24) & 0xFF) / 255.0);
- TRACE("Color value (ARGB) : %08lx", dwColor);
+ TRACE("Color value (ARGB) : %08lx\n", dwColor);
}
glClear(bitfield);
--- ../wine_work_base/dlls/ddraw/ddraw_private.h Wed Nov 27 23:01:56 2002
+++ dlls/ddraw/ddraw_private.h Fri Nov 29 21:58:53 2002
@@ -368,4 +368,28 @@
extern void DDRAW_dump_lockflag(DWORD lockflag);
extern void DDRAW_dump_DDCOLORKEY(const DDCOLORKEY *in);
extern void DDRAW_dump_DDCAPS(const DDCAPS *lpcaps);
+
+/* Used for generic dumping */
+typedef struct
+{
+ DWORD val;
+ const char* name;
+} flag_info;
+
+#define FE(x) { x, #x }
+
+typedef struct
+{
+ DWORD val;
+ const char* name;
+ void (*func)(const void *);
+ ptrdiff_t offset;
+} member_info;
+
+#define DDRAW_dump_flags(flags,names,num_names) DDRAW_dump_flags_(flags, names, num_names, 1)
+#define ME(x,f,e) { x, #x, (void (*)(const void *))(f), offsetof(STRUCT, e) }
+
+extern void DDRAW_dump_flags_(DWORD flags, const flag_info* names, size_t num_names, int newline);
+extern void DDRAW_dump_members(DWORD flags, const void* data, const member_info* mems, size_t num_mems);
+
#endif /* __WINE_DLLS_DDRAW_DDRAW_PRIVATE_H */
--- ../wine_work_base/dlls/ddraw/helper.c Wed Nov 27 23:01:56 2002
+++ dlls/ddraw/helper.c Fri Nov 29 21:58:21 2002
@@ -39,29 +39,8 @@
/******************************************************************************
* debug output functions
*/
-typedef struct
-{
- DWORD val;
- const char* name;
-} flag_info;
-
-#define FE(x) { x, #x }
-
-typedef struct
-{
- DWORD val;
- const char* name;
- void (*func)(const void *);
- ptrdiff_t offset;
-} member_info;
-
-#define ME(x,f,e) { x, #x, (void (*)(const void *))(f), offsetof(STRUCT, e) }
-
-#define DDRAW_dump_flags(flags,names,num_names) \
- DDRAW_dump_flags_(flags, names, num_names, 1)
-
-static void DDRAW_dump_flags_(DWORD flags, const flag_info* names,
- size_t num_names, int newline)
+void DDRAW_dump_flags_(DWORD flags, const flag_info* names,
+ size_t num_names, int newline)
{
unsigned int i;
@@ -74,8 +53,8 @@
DPRINTF("\n");
}
-static void DDRAW_dump_members(DWORD flags, const void* data,
- const member_info* mems, size_t num_mems)
+void DDRAW_dump_members(DWORD flags, const void* data,
+ const member_info* mems, size_t num_mems)
{
unsigned int i;
--- ../wine_work_base/dlls/ddraw/d3ddevice/mesa.c Wed Nov 27 23:05:15 2002
+++ dlls/ddraw/d3ddevice/mesa.c Fri Nov 29 23:14:18 2002
@@ -607,6 +607,45 @@
return DD_OK;
}
+inline static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
+{
+ switch (d3dpt) {
+ case D3DPT_POINTLIST:
+ TRACE("Start POINTS\n");
+ glBegin(GL_POINTS);
+ break;
+
+ case D3DPT_LINELIST:
+ TRACE("Start LINES\n");
+ glBegin(GL_LINES);
+ break;
+
+ case D3DPT_LINESTRIP:
+ TRACE("Start LINE_STRIP\n");
+ glBegin(GL_LINE_STRIP);
+ break;
+
+ case D3DPT_TRIANGLELIST:
+ TRACE("Start TRIANGLES\n");
+ glBegin(GL_TRIANGLES);
+ break;
+
+ case D3DPT_TRIANGLESTRIP:
+ TRACE("Start TRIANGLE_STRIP\n");
+ glBegin(GL_TRIANGLE_STRIP);
+ break;
+
+ case D3DPT_TRIANGLEFAN:
+ TRACE("Start TRIANGLE_FAN\n");
+ glBegin(GL_TRIANGLE_FAN);
+ break;
+
+ default:
+ TRACE("Unhandled primitive\n");
+ break;
+ }
+}
+
inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
{
@@ -684,42 +723,8 @@
glThis->vertex_type = d3dvt;
}
- switch (d3dpt) {
- case D3DPT_POINTLIST:
- TRACE("Start POINTS\n");
- glBegin(GL_POINTS);
- break;
-
- case D3DPT_LINELIST:
- TRACE("Start LINES\n");
- glBegin(GL_LINES);
- break;
-
- case D3DPT_LINESTRIP:
- TRACE("Start LINE_STRIP\n");
- glBegin(GL_LINE_STRIP);
- break;
-
- case D3DPT_TRIANGLELIST:
- TRACE("Start TRIANGLES\n");
- glBegin(GL_TRIANGLES);
- break;
-
- case D3DPT_TRIANGLESTRIP:
- TRACE("Start TRIANGLE_STRIP\n");
- glBegin(GL_TRIANGLE_STRIP);
- break;
-
- case D3DPT_TRIANGLEFAN:
- TRACE("Start TRIANGLE_FAN\n");
- glBegin(GL_TRIANGLE_FAN);
- break;
-
- default:
- TRACE("Unhandled primitive\n");
- break;
- }
-
+ draw_primitive_start_GL(d3dpt);
+
/* Draw the primitives */
for (vx_index = 0; vx_index < maxvert; vx_index++) {
switch (d3dvt) {
@@ -748,9 +753,10 @@
D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
DWORD col = vx->u5.color;
- glColor3f(((col >> 16) & 0xFF) / 255.0,
- ((col >> 8) & 0xFF) / 255.0,
- ((col >> 0) & 0xFF) / 255.0);
+ glColor4ub((col >> 24) & 0xFF,
+ (col >> 16) & 0xFF,
+ (col >> 8) & 0xFF,
+ (col >> 0) & 0xFF);
glTexCoord2f(vx->u7.tu, vx->u8.tv);
if (vx->u4.rhw < 0.01)
glVertex3f(vx->u1.sx,
@@ -835,6 +841,131 @@
return ret_value;
}
+static void dump_flexible_vertex(DWORD d3dvtVertexType)
+{
+ static const flag_info flags[] = {
+ FE(D3DFVF_NORMAL),
+ FE(D3DFVF_RESERVED1),
+ FE(D3DFVF_DIFFUSE),
+ FE(D3DFVF_SPECULAR)
+ };
+ if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
+ switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
+#define GEN_CASE(a) case a: DPRINTF(#a " "); break
+ GEN_CASE(D3DFVF_XYZ);
+ GEN_CASE(D3DFVF_XYZRHW);
+ GEN_CASE(D3DFVF_XYZB1);
+ GEN_CASE(D3DFVF_XYZB2);
+ GEN_CASE(D3DFVF_XYZB3);
+ GEN_CASE(D3DFVF_XYZB4);
+ GEN_CASE(D3DFVF_XYZB5);
+ }
+ DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
+ switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
+ GEN_CASE(D3DFVF_TEX0);
+ GEN_CASE(D3DFVF_TEX1);
+ GEN_CASE(D3DFVF_TEX2);
+ GEN_CASE(D3DFVF_TEX3);
+ GEN_CASE(D3DFVF_TEX4);
+ GEN_CASE(D3DFVF_TEX5);
+ GEN_CASE(D3DFVF_TEX6);
+ GEN_CASE(D3DFVF_TEX7);
+ GEN_CASE(D3DFVF_TEX8);
+ }
+#undef GEN_CASE
+ DPRINTF("\n");
+}
+
+/* Some types used by the fast paths... */
+typedef struct {
+ float x, y, z;
+ float nx, ny, nz;
+ DWORD dwDiffuseRGBA;
+ float tu1, tv1;
+} D3DFVF_VERTEX_1;
+
+static void draw_primitive_7(IDirect3DDeviceImpl *This,
+ D3DPRIMITIVETYPE d3dptPrimitiveType,
+ DWORD d3dvtVertexType,
+ LPVOID lpvVertices,
+ DWORD dwVertexCount,
+ LPWORD dwIndices,
+ DWORD dwIndexCount,
+ DWORD dwFlags)
+{
+ if (TRACE_ON(ddraw)) {
+ TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
+ }
+
+ ENTER_GL();
+ draw_primitive_start_GL(d3dptPrimitiveType);
+
+ /* Some fast paths first before the generic case.... */
+ if (d3dvtVertexType == D3DFVF_VERTEX) {
+ D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
+ int index;
+
+ for (index = 0; index < dwIndexCount; index++) {
+ int i = (dwIndices == NULL) ? index : dwIndices[index];
+
+ glNormal3f(vertices[i].nx, vertices[i].ny, vertices[i].nz);
+ glTexCoord2f(vertices[i].tu1, vertices[i].tv1);
+ glColor4ub((vertices[i].dwDiffuseRGBA >> 24) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 16) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 8) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 0) & 0xFF);
+ glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
+ TRACE(" %f %f %f / %f %f %f (%02lx %02lx %02lx %02lx) (%f %f)\n",
+ vertices[i].x, vertices[i].y, vertices[i].z,
+ vertices[i].nx, vertices[i].ny, vertices[i].nz,
+ (vertices[i].dwDiffuseRGBA >> 24) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 16) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 8) & 0xFF,
+ (vertices[i].dwDiffuseRGBA >> 0) & 0xFF,
+ vertices[i].tu1, vertices[i].tv1);
+ }
+ }
+
+ glEnd();
+ LEAVE_GL();
+ TRACE("End\n");
+}
+
+
+HRESULT WINAPI
+GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
+ D3DPRIMITIVETYPE d3dptPrimitiveType,
+ DWORD d3dvtVertexType,
+ LPVOID lpvVertices,
+ DWORD dwVertexCount,
+ DWORD dwFlags)
+{
+ ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
+ TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
+
+ draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
+
+ return DD_OK;
+}
+
+HRESULT WINAPI
+GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
+ D3DPRIMITIVETYPE d3dptPrimitiveType,
+ DWORD d3dvtVertexType,
+ LPVOID lpvVertices,
+ DWORD dwVertexCount,
+ LPWORD dwIndices,
+ DWORD dwIndexCount,
+ DWORD dwFlags)
+{
+ ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
+ TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
+
+ draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
+
+ return DD_OK;
+}
+
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
#else
@@ -869,8 +1000,8 @@
XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
- XCAST(DrawPrimitive) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
- XCAST(DrawIndexedPrimitive) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
+ XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
+ XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
XCAST(DrawPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
@@ -1044,8 +1175,97 @@
#undef XCAST
#endif
+/* TODO for both these functions :
+ - change / restore OpenGL parameters for pictures transfers in case they are ever modified
+ by other OpenGL code in D3D
+ - handle the case where no 'Begin / EndScene' was done between two locks
+ - handle the rectangles in the unlock too
+*/
+static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
+{
+ /* First, check if we need to do anything */
+ if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
+ GLenum buffer_type;
+ GLenum prev_read;
+ RECT loc_rect;
+
+ ENTER_GL();
+
+ glGetIntegerv(GL_READ_BUFFER, &prev_read);
+ glFlush();
+
+ WARN(" application does a lock on a 3D surface - expect slow downs.\n");
+ if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
+ /* Application wants to lock the front buffer */
+ glReadBuffer(GL_FRONT);
+ } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
+ /* Application wants to lock the back buffer */
+ glReadBuffer(GL_BACK);
+ } else {
+ WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
+ }
+ if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
+ buffer_type = GL_UNSIGNED_SHORT_5_6_5;
+ } else {
+ WARN(" unsupported pixel format.\n");
+ LEAVE_GL();
+ 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;
+ } else {
+ loc_rect = *pRect;
+ }
+ glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
+ GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
+ + loc_rect.top * This->surface_desc.u1.lPitch
+ + loc_rect.left * GET_BPP(This->surface_desc)));
+ glReadBuffer(prev_read);
+ LEAVE_GL();
+ }
+}
+static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
+{
+ /* First, check if we need to do anything */
+ if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
+ GLenum buffer_type;
+ GLenum prev_draw;;
+
+ ENTER_GL();
+
+ glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
+
+ WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
+ if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
+ /* Application wants to lock the front buffer */
+ glDrawBuffer(GL_FRONT);
+ } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
+ /* Application wants to lock the back buffer */
+ glDrawBuffer(GL_BACK);
+ } else {
+ WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
+ }
+
+ if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
+ buffer_type = GL_UNSIGNED_SHORT_5_6_5;
+ } else {
+ WARN(" unsupported pixel format.\n");
+ LEAVE_GL();
+ return;
+ }
+
+ glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
+ GL_RGB, buffer_type, This->surface_desc.lpSurface);
+ glDrawBuffer(prev_draw);
+
+ LEAVE_GL();
+ }
+}
HRESULT
d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
@@ -1057,6 +1277,7 @@
XVisualInfo *vis;
int num;
XVisualInfo template;
+ GLenum buffer;
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
if (object == NULL) return DDERR_OUTOFMEMORY;
@@ -1070,14 +1291,14 @@
object->current_viewport = NULL;
object->current_texture = NULL;
object->set_context = set_context;
-
+
TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
device_context = GetDC(surface->ddraw_owner->window);
gl_object->display = get_display(device_context);
gl_object->drawable = get_drawable(device_context);
ReleaseDC(surface->ddraw_owner->window,device_context);
-
+
ENTER_GL();
template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
@@ -1105,12 +1326,29 @@
/* Look for the front buffer and override its surface's Flip method (if in double buffering) */
for (surf = surface; surf != NULL; surf = surf->surface_owner) {
if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
- surface->surface_owner->aux_ctx = (LPVOID) gl_object->display;
- surface->surface_owner->aux_data = (LPVOID) gl_object->drawable;
- surface->surface_owner->aux_flip = opengl_flip;
+ surf->aux_ctx = (LPVOID) gl_object->display;
+ surf->aux_data = (LPVOID) gl_object->drawable;
+ surf->aux_flip = opengl_flip;
+ buffer = GL_BACK;
break;
}
}
+ /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
+ if (surf == NULL) {
+ TRACE(" no double buffering : drawing on the front buffer\n");
+ buffer = GL_FRONT;
+ }
+
+ for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
+ for (; surf != NULL; surf = surf->next_attached) {
+ if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
+ ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
+ /* Override the Lock / Unlock function for all these surfaces */
+ surf->lock_update = d3ddevice_lock_update;
+ surf->unlock_update = d3ddevice_unlock_update;
+ }
+ surf->d3ddevice = object;
+ }
gl_object->render_state.src = GL_ONE;
gl_object->render_state.dst = GL_ZERO;
@@ -1135,6 +1373,9 @@
TRACE(" current context set\n");
glClearColor(0.0, 0.0, 0.0, 0.0);
glColor3f(1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ glDrawBuffer(buffer);
+ /* 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();
/* fill_device_capabilities(d3d->ddraw); */
More information about the wine-patches
mailing list