Hello!
I wrote a patch to query the amount of videoram via the NV-CONTROL and
ATIFGLEXTENSION Xserver extensions. The problem is: I have no access to a box
with an ATI adapter to test it. Therefore, I'm sending the patch to
wine-devel rather than to wine-patches. Perhaps somebody with an ATI card
could test the patch. Alternatively, I attached a small test program which
just prints the amount of videoram to stdout and uses the same code as the
patch.
Fabian
From c1b2f368aa4580faef68cc0eaff0c5387e3eb8bf Mon Sep 17 00:00:00 2001
From: Fabian Bieler <der.fabe(a)gmx.net>
Date: Fri, 6 Oct 2006 00:07:00 +0200
Subject: [PATCH] use NV-CONTROL and ATIFGLEXTENSION Xserver extensions to query amount of videoram
---
dlls/wined3d/device.c | 26 +---
dlls/wined3d/directx.c | 36 +++++
dlls/wined3d/wined3d_private.h | 1
dlls/winex11.drv/Makefile.in | 1
dlls/winex11.drv/init.c | 7 +
dlls/winex11.drv/opengl.c | 17 +++
dlls/winex11.drv/vendor_specific.c | 242 ++++++++++++++++++++++++++++++++++++
dlls/winex11.drv/x11drv.h | 6 +
8 files changed, 312 insertions(+), 24 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 82c8044..3358111 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1061,7 +1061,7 @@ static HRESULT WINAPI IWineD3DDeviceImp
/** TODO: change this into a texture transform matrix so that it's processed in hardware **/
- TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
+ TRACE("Pool %d %d %d %d",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
/** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
* this function is too deap to need to care about things like this.
@@ -2305,24 +2305,12 @@ static HRESULT WINAPI IWineD3DDeviceImpl
}
static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
- /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
- * Into the video ram as possible and seeing how many fit
- * you can also get the correct initial value from nvidia and ATI's driver via X
- * texture memory is video memory + AGP memory
- *******************/
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
- static BOOL showfixmes = TRUE;
- if (showfixmes) {
- FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
- (wined3d_settings.emulated_textureram/(1024*1024)),
- ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
- showfixmes = FALSE;
- }
- TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
- (wined3d_settings.emulated_textureram/(1024*1024)),
- ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
- /* return simulated texture memory left */
- return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
+
+ TRACE("(%p) : emulating %dMib, returning %dMib\n", This, (This->videoRam/1024),
+ ((This->videoRam*1024 - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
+ /* videomemory is simulated videomemory + AGP memory left */
+ return (This->videoRam*1024 - wineD3DGlobalStatistics->glsurfaceram);
}
@@ -5909,7 +5897,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
IWineD3DStateBlockImpl *object;
HRESULT temp_result;
- TRACE("(%p)\n", This);
+ TRACE("(%p)", This);
if (This->isRecordingState) {
return WINED3DERR_INVALIDCALL;
diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 33b4fb5..4205986 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -42,9 +42,17 @@ #define GLINFO_LOCATION This->gl_info
#define X11DRV_ESCAPE 6789
enum x11drv_escape_codes
{
- X11DRV_GET_DISPLAY, /* get X11 display for a DC */
- X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
- X11DRV_GET_FONT, /* get current X font for a DC */
+ X11DRV_GET_DISPLAY, /* get X11 display for a DC */
+ X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
+ X11DRV_GET_FONT, /* get current X font for a DC */
+ X11DRV_SET_DRAWABLE, /* set current drawable for a DC */
+ X11DRV_START_EXPOSURES, /* start graphics exposures */
+ X11DRV_END_EXPOSURES, /* end graphics exposures */
+ X11DRV_GET_DCE, /* get the DCE pointer */
+ X11DRV_SET_DCE, /* set the DCE pointer */
+ X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
+ X11DRV_SYNC_PIXMAP, /* sync the dibsection to its pixmap */
+ X11DRV_GET_VIDEORAM /* get videoram in kBytes */
};
/* retrieve the X display to use on a given DC */
@@ -158,6 +166,25 @@ static void WineD3D_ReleaseFakeGLContext
}
}
+/* returns videoRam in kBytes */
+static unsigned int IWineD3DImpl_GetVideoRam( HDC hdc )
+{
+ unsigned int videoRam;
+ enum x11drv_escape_codes escape = X11DRV_GET_VIDEORAM;
+
+ if (ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
+ sizeof(videoRam), (LPSTR)&videoRam ))
+ {
+ TRACE("Using %u kByte\n", videoRam);
+ return videoRam;
+ }
+ else
+ {
+ TRACE("Using default of %u kByte\n", wined3d_settings.emulated_textureram);
+ return wined3d_settings.emulated_textureram;
+ }
+}
+
/**********************************************************
* IUnknown parts follows
**********************************************************/
@@ -1589,7 +1616,7 @@ static HRESULT WINAPI IWineD3DImpl_Check
static HRESULT WINAPI IWineD3DImpl_CheckDeviceFormat(IWineD3D *iface, UINT Adapter, WINED3DDEVTYPE DeviceType,
WINED3DFORMAT AdapterFormat, DWORD Usage, WINED3DRESOURCETYPE RType, WINED3DFORMAT CheckFormat) {
IWineD3DImpl *This = (IWineD3DImpl *)iface;
- TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n",
+ TRACE_(d3d_caps)("(%p)-> (STUB) (Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%u,%s,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s)) ",
This,
Adapter,
DeviceType, debug_d3ddevicetype(DeviceType),
@@ -2396,6 +2423,7 @@ static HRESULT WINAPI IWineD3DImpl_Crea
/* Initialize other useful values */
object->adapterNo = Adapter;
object->devType = DeviceType;
+ object->videoRam = IWineD3DImpl_GetVideoRam(GetDC(0));
TRACE("(%p) : Creating stateblock\n", This);
/* Creating the startup stateBlock - Note Special Case: 0 => Don't fill in yet! */
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index b859ade..8563bac 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -527,6 +527,7 @@ #define NEEDS_DI
WINED3DDEVICE_CREATION_PARAMETERS createParms;
UINT adapterNo;
D3DDEVTYPE devType;
+ UINT videoRam; /* emulated videoram in kByte */
IWineD3DSwapChain **swapchains;
uint NumberOfSwapChains;
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in
index 200bec6..cc8439a 100644
--- a/dlls/winex11.drv/Makefile.in
+++ b/dlls/winex11.drv/Makefile.in
@@ -32,6 +32,7 @@ C_SRCS = \
scroll.c \
settings.c \
text.c \
+ vendor_specific.c \
window.c \
winpos.c \
wintab.c \
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c
index b3ee171..987826c 100644
--- a/dlls/winex11.drv/init.c
+++ b/dlls/winex11.drv/init.c
@@ -422,6 +422,13 @@ INT X11DRV_ExtEscape( X11DRV_PDEVICE *ph
}
return FALSE;
break;
+ case X11DRV_GET_VIDEORAM:
+ if (out_count >= sizeof(unsigned int))
+ {
+ *(unsigned int *)out_data = get_videoram(gdi_display);
+ return TRUE;
+ }
+ break;
}
}
break;
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c
index 64b1166..f1f623b 100644
--- a/dlls/winex11.drv/opengl.c
+++ b/dlls/winex11.drv/opengl.c
@@ -2648,6 +2648,16 @@ BOOL destroy_glxpixmap(XID glxpixmap)
return TRUE;
}
+const char *get_glversion()
+{
+ if (!has_opengl()) {
+ ERR("No libGL on this box - disabling OpenGL support !\n");
+ return NULL;
+ }
+
+ return WineGLInfo.glVersion;
+}
+
/**
* X11DRV_SwapBuffers
*
@@ -2863,4 +2873,11 @@ BOOL destroy_glxpixmap(XID glxpixmap)
return FALSE;
}
+const char *get_glversion()
+{
+ ERR_(opengl)("No OpenGL support compiled in.\n");
+ return NULL;
+}
+
+
#endif /* defined(HAVE_OPENGL) */
diff --git a/dlls/winex11.drv/vendor_specific.c b/dlls/winex11.drv/vendor_specific.c
new file mode 100644
index 0000000..350c659
--- /dev/null
+++ b/dlls/winex11.drv/vendor_specific.c
@@ -0,0 +1,242 @@
+/*
+ * X11DRV vendor specific Xserver extensions
+ *
+ * Copyright 2006 Fabian Bieler
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+
+#include "x11drv.h"
+#include "wine/debug.h"
+
+#include <X11/Xlibint.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
+
+/* from "NVCtrl.h" */
+#define NV_CTRL_VIDEO_RAM 6
+
+/* from "nv_control.h" */
+#define NV_CONTROL_NAME "NV-CONTROL"
+#define NV_CONTROL_EVENTS 1
+typedef struct {
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+} xnvCtrlQueryAttributeReq;
+#define sz_xnvCtrlQueryAttributeReq sizeof(xnvCtrlQueryAttributeReq)
+typedef struct {
+ BYTE type;
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 flags B32;
+ INT32 value B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+ CARD32 pad7 B32;
+} xnvCtrlQueryAttributeReply;
+//#define sz_xnvCtrlQueryAttributeReply 32
+#define X_nvCtrlQueryAttribute 2
+
+/* from "R200_extensions.h" "atiddx_extensions.h" respectively */
+#define ATIFGL_EXTENSION_NAME "ATIFGLEXTENSION"
+#define ATIFGL_EXTENSION_EVENTS 0
+typedef struct _FGLGetDriverData {
+ CARD8 reqType;
+ CARD8 fireglReqType;
+ CARD16 length B16;
+ CARD32 screen B32;
+ CARD16 size B16;
+ CARD16 pad1;
+} xFGLGetDriverDataReq;
+#define sz_xFGLGetDriverDataReq sizeof(xFGLGetDriverDataReq)
+typedef union {
+struct {
+ BYTE type;
+ BYTE pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD8 majorVersion;
+ CARD8 minorVersion;
+ CARD8 patchlevel B16;
+ CARD8 BIOSVersionMajor;
+ CARD8 BIOSVersionMinor;
+ CARD8 HasSecondary;
+ CARD16 pad3 B16;
+ CARD16 usBoardType B16;
+ CARD16 usChipType B16;
+ CARD16 usVideoRam B16;
+ CARD8 ATiRevID;
+ CARD8 AGPTransferMode;
+ CARD32 AGPCapPtr;
+ CARD32 AGPStatus;
+ CARD32 AGPCommand;
+ CARD32 ulGamma1 B32;
+ CARD32 ulGamma2 B32;
+ CARD32 ulDriverType B32;
+ CARD32 ulDesktopSetup B32;
+ CARD32 ulPrimary B32;
+} v0;
+struct {
+ BYTE type;
+ BYTE pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD8 majorVersion;
+ CARD8 minorVersion;
+ CARD8 patchlevel B16;
+ CARD8 BIOSVersionMajor;
+ CARD8 BIOSVersionMinor;
+ CARD8 HasSecondary;
+ CARD16 pad3 B16;
+ CARD16 usBoardType B16;
+ CARD16 usChipType B16;
+ CARD16 usVideoRam B16;
+ CARD8 sATiRevID[17];
+ CARD8 AGPTransferMode;
+ CARD32 AGPCapPtr;
+ CARD32 AGPStatus;
+ CARD32 AGPCommand;
+ CARD32 ulGamma1 B32;
+ CARD32 ulGamma2 B32;
+ CARD32 ulDriverType B32;
+ CARD32 ulDesktopSetup B32;
+ CARD32 ulPrimary B32;
+} v3_7;
+struct {
+ BYTE type;
+ BYTE pad1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD8 majorVersion;
+ CARD8 minorVersion;
+ CARD8 patchlevel B16;
+ CARD8 BIOSVersionMajor;
+ CARD8 BIOSVersionMinor;
+ CARD8 HasSecondary;
+ CARD16 pad3 B16;
+ CARD16 usBoardType B16;
+ CARD16 usChipType B16;
+ CARD32 ulVideoRam B32;
+ CARD8 sATiRevID[17];
+ CARD8 AGPTransferMode;
+ CARD32 AGPCapPtr;
+ CARD32 AGPStatus;
+ CARD32 AGPCommand;
+ CARD32 ulGamma1 B32;
+ CARD32 ulGamma2 B32;
+ CARD32 ulDriverType B32;
+ CARD32 ulDesktopSetup B32;
+ CARD32 ulPrimary B32;
+ CARD8 sBoardName[96];
+} v8_24;
+} xFGLGetDriverDataReply;
+#define X_FGLGetDriverData 0
+
+unsigned int get_videoram(Display *dpy)
+{
+ int major_opcode, first_event, first_error;
+ unsigned int vram=0;
+
+ TRACE("Probing videoram...\n");
+
+ /* Try the NV-CONTROL x-server extension: */
+ if(XQueryExtension(dpy, NV_CONTROL_NAME, &major_opcode, &first_event, &first_error)) {
+ xnvCtrlQueryAttributeReply rep;
+ xnvCtrlQueryAttributeReq *req;
+
+ wine_tsx11_lock();
+ GetReq(nvCtrlQueryAttribute, req);
+ req->reqType = major_opcode;
+ req->nvReqType = X_nvCtrlQueryAttribute;
+ req->screen = DefaultScreen(dpy);
+ req->display_mask = 0;
+ req->attribute = NV_CTRL_VIDEO_RAM;
+ if(_XReply(dpy, (xReply *)&rep, 0, xTrue)) {
+ if(rep.flags) {
+ vram=rep.value;
+ TRACE("Got %u kByte from NV-CONTROL\n", vram);
+ }
+ }
+ wine_tsx11_unlock();
+ SyncHandle();
+ }
+
+ /* Try the ATIFGLEXTENSION x-server extension: */
+ if(XQueryExtension(dpy, ATIFGL_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) {
+ xFGLGetDriverDataReq *req;
+ xFGLGetDriverDataReply rep;
+
+ char *v;
+ unsigned short version;
+ int size;
+
+ /* This extension was altered a few times, so we need to get the driver version.
+ * ATI OpenGL version strings are of the form
+ * "<OGLmajor>.<OGLminor>.<OGLpatchlevel> ([XFree86-version-]<DRIVERmajor>.<DRIVERminor>.<DRIVERpatchlevel>)" */
+ v=(char *)get_glversion();
+ v=strchr(v, '(');
+ if(!v) {
+ ERR("Failed to parse ATI OpenGL version string '%s'", get_glversion());
+ }
+ else
+ {
+ v=max(strchr(v, '-'),v);
+ if(*v)v++;
+ version=strtol(v, &v, 10)<<8;
+ if(*v)v++;
+ version+=strtol(v, NULL, 10);
+ if(version<0x0307)
+ size=(sizeof(rep.v0) - 32) >> 2;
+ else if(version<0x0818)
+ size=(sizeof(rep.v3_7) - 32) >> 2;
+ else
+ size=(sizeof(rep.v8_24) - 32) >> 2;
+ TRACE("Found ATI driver version %hhu.%hhu\n", (version&0xff00)>>8, version&0x00ff);
+
+ wine_tsx11_lock();
+ GetReq(FGLGetDriverData, req);
+ req->reqType = major_opcode;
+ req->fireglReqType = X_FGLGetDriverData;
+ req->screen = DefaultScreen(dpy);
+ if(_XReply(dpy, (xReply *)&rep, size, xTrue))
+ {
+ if(version<0x0307) {
+ if(rep.v0.usVideoRam==0x200 || rep.v0.usVideoRam==0x400 || rep.v0.usVideoRam==0x800 || rep.v0.usVideoRam==0x1000)
+ vram=rep.v0.usVideoRam<<6;
+ }
+ else if(version<0x0818) {
+ if(rep.v3_7.usVideoRam==0x200 || rep.v3_7.usVideoRam==0x400 || rep.v3_7.usVideoRam==0x800 || rep.v3_7.usVideoRam==0x1000)
+ vram=rep.v3_7.usVideoRam<<6;
+ }
+ else {
+ vram=rep.v8_24.ulVideoRam;
+ }
+ }
+ TRACE("Got %u kByte from ATIFGLEXTENSION\n", vram);
+ wine_tsx11_unlock();
+ SyncHandle();
+ }
+ }
+
+ return vram;
+}
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index a4eb516..5fb918a 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -271,6 +271,9 @@ extern void X11DRV_XRender_UpdateDrawabl
extern XVisualInfo *X11DRV_setup_opengl_visual(Display *display);
extern Drawable get_glxdrawable(X11DRV_PDEVICE *physDev);
extern BOOL destroy_glxpixmap(XID glxpixmap);
+extern const char *get_glversion();
+
+extern unsigned int get_videoram(Display *dpy);
/* XIM support */
extern XIC X11DRV_CreateIC(XIM xim, Display *display, Window win);
@@ -474,7 +477,8 @@ enum x11drv_escape_codes
X11DRV_GET_DCE, /* get the DCE pointer */
X11DRV_SET_DCE, /* set the DCE pointer */
X11DRV_GET_GLX_DRAWABLE, /* get current glx drawable for a DC */
- X11DRV_SYNC_PIXMAP /* sync the dibsection to its pixmap */
+ X11DRV_SYNC_PIXMAP, /* sync the dibsection to its pixmap */
+ X11DRV_GET_VIDEORAM /* get videoram in kBytes */
};
struct x11drv_escape_set_drawable
--
1.4.1.1