directx.c 44.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * IDirect3D8 implementation
 *
 * Copyright 2002 Jason Edmeades
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

21 22
#include "config.h"

23 24
#include <stdarg.h>

25 26
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
27 28 29
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
30
#include "winuser.h"
31
#include "wine/debug.h"
32
#include "wine/unicode.h"
33 34 35 36 37

#include "d3d8_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

38 39 40 41 42 43 44 45 46
/* x11drv GDI escapes */
#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 */
};

47 48 49 50 51 52 53 54 55
#define NUM_FORMATS 7
static const D3DFORMAT device_formats[NUM_FORMATS] = {
  D3DFMT_P8,
  D3DFMT_R3G3B2,
  D3DFMT_R5G6B5, 
  D3DFMT_X1R5G5B5,
  D3DFMT_X4R4G4B4,
  D3DFMT_R8G8B8,
  D3DFMT_X8R8G8B8
56 57
};

58
static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display);
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
/* retrieve the X display to use on a given DC */
inline static Display *get_display( HDC hdc )
{
    Display *display;
    enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;

    if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
                    sizeof(display), (LPSTR)&display )) display = NULL;
    return display;
}


/* IDirect3D IUnknown parts follow: */
HRESULT WINAPI IDirect3D8Impl_QueryInterface(LPDIRECT3D8 iface,REFIID riid,LPVOID *ppobj)
{
    ICOM_THIS(IDirect3D8Impl,iface);

    if (IsEqualGUID(riid, &IID_IUnknown)
Raphael Junqueira's avatar
Raphael Junqueira committed
78
        || IsEqualGUID(riid, &IID_IDirect3D8)) {
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
        IDirect3D8Impl_AddRef(iface);
        *ppobj = This;
        return D3D_OK;
    }

    WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
    return E_NOINTERFACE;
}

ULONG WINAPI IDirect3D8Impl_AddRef(LPDIRECT3D8 iface) {
    ICOM_THIS(IDirect3D8Impl,iface);
    TRACE("(%p) : AddRef from %ld\n", This, This->ref);
    return ++(This->ref);
}

ULONG WINAPI IDirect3D8Impl_Release(LPDIRECT3D8 iface) {
    ICOM_THIS(IDirect3D8Impl,iface);
    ULONG ref = --This->ref;
    TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
    if (ref == 0)
        HeapFree(GetProcessHeap(), 0, This);
    return ref;
}

/* IDirect3D Interface follow: */
HRESULT  WINAPI  IDirect3D8Impl_RegisterSoftwareDevice     (LPDIRECT3D8 iface, void* pInitializeFunction) {
    ICOM_THIS(IDirect3D8Impl,iface);
    FIXME("(%p)->(%p): stub\n", This, pInitializeFunction);
    return D3D_OK;
}

UINT     WINAPI  IDirect3D8Impl_GetAdapterCount            (LPDIRECT3D8 iface) {
    ICOM_THIS(IDirect3D8Impl,iface);
    /* FIXME: Set to one for now to imply the display */
    TRACE("(%p): Mostly stub, only returns primary display\n", This);
    return 1;
}

HRESULT  WINAPI  IDirect3D8Impl_GetAdapterIdentifier       (LPDIRECT3D8 iface,
                                                            UINT Adapter, DWORD Flags, D3DADAPTER_IDENTIFIER8* pIdentifier) {
    ICOM_THIS(IDirect3D8Impl,iface);

    TRACE("(%p}->(Adapter: %d, Flags: %lx, pId=%p)\n", This, Adapter, Flags, pIdentifier);

    if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
        return D3DERR_INVALIDCALL;
    }

    if (Adapter == 0) { /* Display */
        strcpy(pIdentifier->Driver, "Display");
        strcpy(pIdentifier->Description, "Direct3D Display");
        pIdentifier->DriverVersion.s.HighPart = 1;
        pIdentifier->DriverVersion.s.LowPart = 0;
        pIdentifier->VendorId = 0;
        pIdentifier->DeviceId = 0;
        pIdentifier->SubSysId = 0;
        pIdentifier->Revision = 0;
        /*FIXME: memcpy(&pIdentifier->DeviceIdentifier, ??, sizeof(??GUID)); */
137
        if (Flags & D3DENUM_NO_WHQL_LEVEL) {
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
            pIdentifier->WHQLLevel = 0;
        } else {
            pIdentifier->WHQLLevel = 1;
        }
    } else {
        FIXME("Adapter not primary display\n");
    }

    return D3D_OK;
}

UINT     WINAPI  IDirect3D8Impl_GetAdapterModeCount        (LPDIRECT3D8 iface,
                                                            UINT Adapter) {
    ICOM_THIS(IDirect3D8Impl,iface);

    TRACE("(%p}->(Adapter: %d)\n", This, Adapter);

    if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
        return D3DERR_INVALIDCALL;
    }

    if (Adapter == 0) { /* Display */
160 161 162 163 164
        DEVMODEW DevModeW;
        int i = 0;

        while (EnumDisplaySettingsExW(NULL, i, &DevModeW, 0)) {
            i++;
165
        }
166
        TRACE("(%p}->(Adapter: %d) => %d\n", This, Adapter, i);
167
        return i;
168 169 170 171
    } else {
        FIXME("Adapter not primary display\n");
    }

172
    return 0;
173 174 175 176 177 178
}

HRESULT  WINAPI  IDirect3D8Impl_EnumAdapterModes           (LPDIRECT3D8 iface,
                                                            UINT Adapter, UINT Mode, D3DDISPLAYMODE* pMode) {
    ICOM_THIS(IDirect3D8Impl,iface);

179
    TRACE("(%p}->(Adapter:%d, mode:%d, pMode:%p)\n", This, Adapter, Mode, pMode);
180 181 182 183 184 185 186 187

    if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
        return D3DERR_INVALIDCALL;
    }

    if (Adapter == 0) { /* Display */
        HDC hdc;
        int bpp = 0;
188 189 190 191 192 193
        DEVMODEW DevModeW;

        if (EnumDisplaySettingsExW(NULL, Mode, &DevModeW, 0)) 
        {
            pMode->Width        = DevModeW.dmPelsWidth;
            pMode->Height       = DevModeW.dmPelsHeight;
194
            bpp                 = DevModeW.dmBitsPerPel;
195
            pMode->RefreshRate  = D3DADAPTER_DEFAULT;
196 197 198 199
            if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
            {
                pMode->RefreshRate = DevModeW.dmDisplayFrequency;
            }
200 201 202
        }
        else
        {
203 204 205 206 207
            TRACE("Requested mode out of range %d\n", Mode);
            return D3DERR_INVALIDCALL;
        }

        hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
208
        bpp = min(GetDeviceCaps(hdc, BITSPIXEL), bpp);
209 210 211
        DeleteDC(hdc);

        switch (bpp) {
212 213
        case  8: pMode->Format = D3DFMT_R3G3B2;   break;
        case 16: pMode->Format = D3DFMT_R5G6B5;   break;
214
        case 24: /* pMode->Format = D3DFMT_R5G6B5;   break;*/ /* Make 24bit appear as 32 bit */
215 216
        case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
        default: pMode->Format = D3DFMT_UNKNOWN;
217
        }
218
        TRACE("W %d H %d rr %d fmt (%x,%s) bpp %u\n", pMode->Width, pMode->Height, pMode->RefreshRate, pMode->Format, debug_d3dformat(pMode->Format), bpp);
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

    } else {
        FIXME("Adapter not primary display\n");
    }

    return D3D_OK;
}

HRESULT  WINAPI  IDirect3D8Impl_GetAdapterDisplayMode      (LPDIRECT3D8 iface,
                                                            UINT Adapter, D3DDISPLAYMODE* pMode) {
    ICOM_THIS(IDirect3D8Impl,iface);
    TRACE("(%p}->(Adapter: %d, pMode: %p)\n", This, Adapter, pMode);

    if (Adapter >= IDirect3D8Impl_GetAdapterCount(iface)) {
        return D3DERR_INVALIDCALL;
    }

    if (Adapter == 0) { /* Display */
        int bpp = 0;
238
        DEVMODEW DevModeW;
239

240 241 242 243 244 245 246 247 248
        EnumDisplaySettingsExW(NULL, (DWORD)-1, &DevModeW, 0);
        pMode->Width        = DevModeW.dmPelsWidth;
        pMode->Height       = DevModeW.dmPelsHeight;
        bpp                 = DevModeW.dmBitsPerPel;
        pMode->RefreshRate  = D3DADAPTER_DEFAULT;
        if (DevModeW.dmFields&DM_DISPLAYFREQUENCY)
        {
            pMode->RefreshRate = DevModeW.dmDisplayFrequency;
        }
249 250 251

        switch (bpp) {
        case  8: pMode->Format       = D3DFMT_R3G3B2;   break;
252
        case 16: pMode->Format       = D3DFMT_R5G6B5;   break;
253
        case 24: /*pMode->Format       = D3DFMT_R5G6B5;   break;*/ /* Make 24bit appear as 32 bit */
254 255 256 257 258 259 260 261
        case 32: pMode->Format       = D3DFMT_A8R8G8B8; break;
        default: pMode->Format       = D3DFMT_UNKNOWN;
        }

    } else {
        FIXME("Adapter not primary display\n");
    }

262
    TRACE("returning w:%d, h:%d, ref:%d, fmt:%x\n", pMode->Width,
263 264 265 266 267 268 269 270
          pMode->Height, pMode->RefreshRate, pMode->Format);
    return D3D_OK;
}

HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceType            (LPDIRECT3D8 iface,
                                                            UINT Adapter, D3DDEVTYPE CheckType, D3DFORMAT DisplayFormat,
                                                            D3DFORMAT BackBufferFormat, BOOL Windowed) {
    ICOM_THIS(IDirect3D8Impl,iface);
271 272 273 274 275 276 277
    FIXME("(%p)->(Adptr:%d, CheckType:(%x,%s), DispFmt:(%x,%s), BackBuf:(%x,%s), Win?%d): stub\n", 
	  This, 
	  Adapter, 
	  CheckType, debug_d3ddevicetype(CheckType),
          DisplayFormat, debug_d3dformat(DisplayFormat),
	  BackBufferFormat, debug_d3dformat(BackBufferFormat),
	  Windowed);
278 279 280 281 282 283 284
    return D3D_OK;
}

HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceFormat          (LPDIRECT3D8 iface,
                                                            UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
                                                            DWORD Usage, D3DRESOURCETYPE RType, D3DFORMAT CheckFormat) {
    ICOM_THIS(IDirect3D8Impl,iface);
285 286 287 288 289 290 291 292 293
    FIXME("(%p)->(Adptr:%d, DevType:(%u,%s), AdptFmt:(%u,%s), Use:(%lu,%s), ResTyp:(%x,%s), CheckFmt:(%u,%s))\n", 
          This, 
	  Adapter, 
	  DeviceType, debug_d3ddevicetype(DeviceType), 
	  AdapterFormat, debug_d3dformat(AdapterFormat), 
	  Usage, debug_d3dusage(Usage),
	  RType, debug_d3dressourcetype(RType), 
	  CheckFormat, debug_d3dformat(CheckFormat));

294 295 296 297 298 299
    if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
        switch (CheckFormat) {
        case D3DFMT_DXT1:
        case D3DFMT_DXT3:
        case D3DFMT_DXT5:
            return D3D_OK;
300 301
        default:
            break; /* Avoid compiler warnings */
302 303 304
        }
    }

305
    switch (CheckFormat) {
306 307 308 309 310 311 312 313 314 315
    case D3DFMT_UYVY:
    case D3DFMT_YUY2:
    case D3DFMT_DXT1:
    case D3DFMT_DXT2:
    case D3DFMT_DXT3:
    case D3DFMT_DXT4:
    case D3DFMT_DXT5:
    case D3DFMT_X8L8V8U8:
    case D3DFMT_L6V5U5:
    case D3DFMT_V8U8:
316 317 318 319
      /* Since we do not support these formats right now, don't pretend to. */
      return D3DERR_NOTAVAILABLE;
    default:
      break;
320
    }
321

322 323 324
    return D3D_OK;
}

325 326 327
HRESULT  WINAPI  IDirect3D8Impl_CheckDeviceMultiSampleType(LPDIRECT3D8 iface,
							   UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT SurfaceFormat,
							   BOOL Windowed, D3DMULTISAMPLE_TYPE MultiSampleType) {
328
    ICOM_THIS(IDirect3D8Impl,iface);
329 330 331 332 333 334 335 336 337 338 339
    FIXME("(%p)->(Adptr:%d, DevType:(%x,%s), SurfFmt:(%x,%s), Win?%d, MultiSamp:%x)\n", 
	  This, 
	  Adapter, 
	  DeviceType, debug_d3ddevicetype(DeviceType),
          SurfaceFormat, debug_d3dformat(SurfaceFormat),
	  Windowed, 
	  MultiSampleType);
  
    if (D3DMULTISAMPLE_NONE == MultiSampleType)
      return D3D_OK;
    return D3DERR_NOTAVAILABLE;
340 341
}

342 343 344
HRESULT  WINAPI  IDirect3D8Impl_CheckDepthStencilMatch(LPDIRECT3D8 iface, 
						       UINT Adapter, D3DDEVTYPE DeviceType, D3DFORMAT AdapterFormat,
						       D3DFORMAT RenderTargetFormat, D3DFORMAT DepthStencilFormat) {
345
    ICOM_THIS(IDirect3D8Impl,iface);
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
    FIXME("(%p)->(Adptr:%d, DevType:(%x,%s), AdptFmt:(%x,%s), RendrTgtFmt:(%x,%s), DepthStencilFmt:(%x,%s))\n", 
	  This, 
	  Adapter, 
	  DeviceType, debug_d3ddevicetype(DeviceType),
          AdapterFormat, debug_d3dformat(AdapterFormat),
	  RenderTargetFormat, debug_d3dformat(RenderTargetFormat), 
	  DepthStencilFormat, debug_d3dformat(DepthStencilFormat));

#if 0
    switch (DepthStencilFormat) {
    case D3DFMT_D24X4S4:
    case D3DFMT_D24X8: 
    case D3DFMT_D24S8: 
    case D3DFMT_D32:
      /**
       * as i don't know how to really check hard caps of graphics cards
       * i prefer to not permit 32bit zbuffers enumeration (as few cards can do it)
       */
      return D3DERR_NOTAVAILABLE;
    default:
      break;
    }
#endif
369 370 371
    return D3D_OK;
}

372
HRESULT  WINAPI  IDirect3D8Impl_GetDeviceCaps(LPDIRECT3D8 iface, UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS8* pCaps) {
373 374 375 376 377 378

    BOOL        gotContext  = FALSE;
    BOOL        created     = FALSE;
    GLint       gl_tex_size = 0;    
    GLXContext  gl_context  = 0;
    Display    *display     = NULL;
379
    ICOM_THIS(IDirect3D8Impl,iface);
380

381 382
    TRACE("(%p)->(Adptr:%d, DevType: %x, pCaps: %p)\n", This, Adapter, DeviceType, pCaps);

383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    /* Note: GL seems to trap if GetDeviceCaps is called before any HWND's created
        ie there is no GL Context - Get a default rendering context to enable the 
        function query some info from GL                                           */    
    if (glXGetCurrentContext() == NULL) {

        XVisualInfo  template;
        XVisualInfo *vis;
        HDC          device_context;
        Visual      *visual;
        Drawable     drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
        XWindowAttributes win_attr;
        BOOL         failed = FALSE;
        int          num;

        /* Get the display */
        device_context = GetDC(0);
        display = get_display(device_context);
        ReleaseDC(0, device_context);

        /* Get the X visual */
        ENTER_GL();
        if (XGetWindowAttributes(display, drawable, &win_attr)) {
            visual = win_attr.visual;
        } else {
            visual = DefaultVisual(display, DefaultScreen(display));
        }
        template.visualid = XVisualIDFromVisual(visual);
        vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
        if (vis == NULL) {
            LEAVE_GL();
            WARN("Error creating visual info for capabilities initialization\n");
            failed = TRUE;
        }

        /* Create a GL context */
        if (!failed) {
           gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);

           if (gl_context == NULL) {
              LEAVE_GL();
              WARN("Error creating default context for capabilities initialization\n");
              failed = TRUE;
           }
        }

        /* Make it the current GL context */
        if (!failed && glXMakeCurrent(display, drawable, gl_context) == False) {
            glXDestroyContext(display, gl_context);
            LEAVE_GL();
            WARN("Error setting default context as current for capabilities initialization\n");
            failed = TRUE;	
        }

        /* It worked! Wow... */
        if (!failed) {
           gotContext = TRUE;
           created = TRUE;
        }
441 442
    } else {
        gotContext = TRUE;
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
    }

    if (gotContext == FALSE) {

        FIXME("GetDeviceCaps called but no GL Context - Returning dummy values\n");
        gl_tex_size=65535;
        pCaps->MaxTextureBlendStages = 2;
        pCaps->MaxSimultaneousTextures = 2;
        pCaps->MaxUserClipPlanes = 8;
        pCaps->MaxActiveLights = 8;
        pCaps->MaxVertexBlendMatrices = 0;
        pCaps->MaxVertexBlendMatrixIndex = 1;
        pCaps->MaxAnisotropy = 0;
        pCaps->MaxPointSize = 255.0;
    } else {
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_tex_size);
    }
460 461 462 463

    /* If we dont know the device settings, go query them now */
    if (This->isGLInfoValid == FALSE) IDirect3D8Impl_FillGLCaps(iface, NULL);

464
    pCaps->DeviceType = (DeviceType == D3DDEVTYPE_HAL) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;  /* Not quite true, but use h/w supported by opengl I suppose */
465 466 467 468 469 470 471 472 473
    pCaps->AdapterOrdinal = Adapter;

    pCaps->Caps = 0;
    pCaps->Caps2 = D3DCAPS2_CANRENDERWINDOWED;
    pCaps->Caps3 = D3DDEVCAPS_HWTRANSFORMANDLIGHT;
    pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_IMMEDIATE;

    pCaps->CursorCaps = 0;

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
    pCaps->DevCaps = D3DDEVCAPS_DRAWPRIMTLVERTEX    | 
                     D3DDEVCAPS_HWTRANSFORMANDLIGHT |
                     D3DDEVCAPS_PUREDEVICE;

    pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_CULLCCW               | 
                               D3DPMISCCAPS_CULLCW                | 
                               D3DPMISCCAPS_COLORWRITEENABLE      |
                               D3DPMISCCAPS_CLIPTLVERTS           |
                               D3DPMISCCAPS_CLIPPLANESCALEDPOINTS | 
                               D3DPMISCCAPS_MASKZ; 
                               /*NOT: D3DPMISCCAPS_TSSARGTEMP*/

    pCaps->RasterCaps = D3DPRASTERCAPS_DITHER   | 
                        D3DPRASTERCAPS_PAT      | 
                        D3DPRASTERCAPS_FOGRANGE;
                        /* FIXME Add:
			   D3DPRASTERCAPS_FOGVERTEX
			   D3DPRASTERCAPS_FOGTABLE
			   D3DPRASTERCAPS_MIPMAPLODBIAS
			   D3DPRASTERCAPS_ZBIAS
			   D3DPRASTERCAPS_ANISOTROPY
			   D3DPRASTERCAPS_WFOG
			   D3DPRASTERCAPS_ZFOG 
			   D3DPRASTERCAPS_COLORPERSPECTIVE
			   D3DPRASTERCAPS_STRETCHBLTMULTISAMPLE
			   D3DPRASTERCAPS_ANTIALIASEDGES
			   D3DPRASTERCAPS_ZBUFFERLESSHSR
			   D3DPRASTERCAPS_WBUFFER */

    pCaps->ZCmpCaps = D3DPCMPCAPS_ALWAYS       | 
                      D3DPCMPCAPS_EQUAL        | 
                      D3DPCMPCAPS_GREATER      | 
                      D3DPCMPCAPS_GREATEREQUAL |
                      D3DPCMPCAPS_LESS         | 
                      D3DPCMPCAPS_LESSEQUAL    | 
                      D3DPCMPCAPS_NEVER        |
                      D3DPCMPCAPS_NOTEQUAL;
511

512 513 514
    pCaps->SrcBlendCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
    pCaps->DestBlendCaps = 0xFFFFFFFF;   /*FIXME: Tidy up later */
    pCaps->AlphaCmpCaps  = 0xFFFFFFFF;   /*FIXME: Tidy up later */
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536

    pCaps->ShadeCaps = D3DPSHADECAPS_SPECULARGOURAUDRGB | 
                       D3DPSHADECAPS_COLORGOURAUDRGB;

    pCaps->TextureCaps =  D3DPTEXTURECAPS_ALPHA        | 
                          D3DPTEXTURECAPS_ALPHAPALETTE | 
                          D3DPTEXTURECAPS_POW2         | 
                          D3DPTEXTURECAPS_VOLUMEMAP    | 
                          D3DPTEXTURECAPS_MIPMAP;
#if defined(GL_VERSION_1_3) || defined(GL_ARB_texture_cube_map)
    pCaps->TextureCaps |= D3DPTEXTURECAPS_CUBEMAP      | 
                          D3DPTEXTURECAPS_MIPCUBEMAP   | 
                          D3DPTEXTURECAPS_CUBEMAP_POW2;
#endif

    pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MAGFLINEAR | 
                               D3DPTFILTERCAPS_MAGFPOINT  | 
                               D3DPTFILTERCAPS_MINFLINEAR | 
                               D3DPTFILTERCAPS_MINFPOINT  |
                               D3DPTFILTERCAPS_MIPFLINEAR | 
                               D3DPTFILTERCAPS_MIPFPOINT;

537 538
    pCaps->CubeTextureFilterCaps = 0;
    pCaps->VolumeTextureFilterCaps = 0;
539 540 541 542

    pCaps->TextureAddressCaps =  D3DPTADDRESSCAPS_BORDER | 
                                 D3DPTADDRESSCAPS_CLAMP  | 
                                 D3DPTADDRESSCAPS_WRAP;
543 544 545
#if defined(GL_VERSION_1_3)
    pCaps->TextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
#endif
546 547 548 549
                                 /* FIXME: Add 
				    D3DPTADDRESSCAPS_BORDER
				    D3DPTADDRESSCAPS_MIRRORONCE */

550 551
    pCaps->VolumeTextureAddressCaps = 0;

552 553 554 555 556 557
    pCaps->LineCaps = D3DLINECAPS_TEXTURE | 
                      D3DLINECAPS_ZTEST;
                      /* FIXME: Add 
			 D3DLINECAPS_BLEND
			 D3DLINECAPS_ALPHACMP
			 D3DLINECAPS_FOG */
558

559 560
    pCaps->MaxTextureWidth = gl_tex_size;
    pCaps->MaxTextureHeight = gl_tex_size;
561

562 563 564 565 566 567 568 569 570 571 572 573 574
    pCaps->MaxVolumeExtent = 0;

    pCaps->MaxTextureRepeat = 32768;
    pCaps->MaxTextureAspectRatio = 32768;
    pCaps->MaxVertexW = 1.0;

    pCaps->GuardBandLeft = 0;
    pCaps->GuardBandTop = 0;
    pCaps->GuardBandRight = 0;
    pCaps->GuardBandBottom = 0;

    pCaps->ExtentsAdjust = 0;

575 576 577 578 579 580 581
    pCaps->StencilCaps =  D3DSTENCILCAPS_DECRSAT | 
                          D3DSTENCILCAPS_INCRSAT | 
                          D3DSTENCILCAPS_INVERT  | 
                          D3DSTENCILCAPS_KEEP    | 
                          D3DSTENCILCAPS_REPLACE | 
                          D3DSTENCILCAPS_ZERO;
#if defined(GL_VERSION_1_4) || defined(GL_EXT_stencil_wrap)
Raphael Junqueira's avatar
Raphael Junqueira committed
582
    pCaps->StencilCaps |= D3DSTENCILCAPS_DECR    | 
583 584
                          D3DSTENCILCAPS_INCR;
#endif
585 586

    pCaps->FVFCaps = D3DFVFCAPS_PSIZE | 0x80000;
587

588 589 590 591 592 593 594 595 596
    pCaps->TextureOpCaps =  D3DTEXOPCAPS_ADD         | 
                            D3DTEXOPCAPS_ADDSIGNED   | 
                            D3DTEXOPCAPS_ADDSIGNED2X |
                            D3DTEXOPCAPS_MODULATE    | 
                            D3DTEXOPCAPS_MODULATE2X  | 
                            D3DTEXOPCAPS_MODULATE4X  |
                            D3DTEXOPCAPS_SELECTARG1  | 
                            D3DTEXOPCAPS_SELECTARG2  | 
                            D3DTEXOPCAPS_DISABLE;
597
#if defined(GL_VERSION_1_3)
598 599
    pCaps->TextureOpCaps |= D3DTEXOPCAPS_DOTPRODUCT3 | 
                            D3DTEXOPCAPS_SUBTRACT;
600
#endif
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
                            /* FIXME: Add 
			      D3DTEXOPCAPS_ADDSMOOTH
			      D3DTEXOPCAPS_BLENDCURRENTALPHA 
			      D3DTEXOPCAPS_BLENDDIFFUSEALPHA 
			      D3DTEXOPCAPS_BLENDFACTORALPHA 
			      D3DTEXOPCAPS_BLENDTEXTUREALPHA 
			      D3DTEXOPCAPS_BLENDTEXTUREALPHAPM 
			      D3DTEXOPCAPS_BUMPENVMAP
			      D3DTEXOPCAPS_BUMPENVMAPLUMINANCE 
			      D3DTEXOPCAPS_LERP 
			      D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR 
			      D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA 
			      D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR 
			      D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
			      D3DTEXOPCAPS_MULTIPLYADD 
			      D3DTEXOPCAPS_PREMODULATE */
617

618
    if (gotContext) {
619
        GLint gl_max;
620
	GLfloat gl_float;
621 622 623
#if defined(GL_VERSION_1_3)
        glGetIntegerv(GL_MAX_TEXTURE_UNITS, &gl_max);
#else
624
        glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
625
#endif
626
        TRACE("GLCaps: GL_MAX_TEXTURE_UNITS_ARB=%d\n", gl_max);
627 628 629 630 631
        pCaps->MaxTextureBlendStages = min(8, gl_max);
        pCaps->MaxSimultaneousTextures = min(8, gl_max);

        glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
        pCaps->MaxUserClipPlanes = min(MAX_CLIPPLANES, gl_max);
632
        TRACE("GLCaps: GL_MAX_CLIP_PLANES=%ld\n", pCaps->MaxUserClipPlanes);
633 634

        glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
635
        pCaps->MaxActiveLights = gl_max;
636
        TRACE("GLCaps: GL_MAX_LIGHTS=%ld\n", pCaps->MaxActiveLights);
637

638 639 640 641 642 643 644 645
        if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
	   glGetIntegerv(GL_MAX_VERTEX_UNITS_ARB, &gl_max);
	   pCaps->MaxVertexBlendMatrices = gl_max;
	   pCaps->MaxVertexBlendMatrixIndex = 1;
        } else {
           pCaps->MaxVertexBlendMatrices = 0;
           pCaps->MaxVertexBlendMatrixIndex = 1;
        }
646

647 648 649 650 651 652 653 654 655 656
#if defined(GL_EXT_texture_filter_anisotropic)
        glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_max);
        pCaps->MaxAnisotropy = gl_max;
#else
        pCaps->MaxAnisotropy = 0;
#endif

	glGetFloatv(GL_POINT_SIZE_RANGE, &gl_float);
	pCaps->MaxPointSize = gl_float;
    }
657

658 659 660 661 662 663 664
    pCaps->VertexProcessingCaps = D3DVTXPCAPS_DIRECTIONALLIGHTS | 
                                  D3DVTXPCAPS_MATERIALSOURCE7   | 
                                  D3DVTXPCAPS_POSITIONALLIGHTS  | 
                                  D3DVTXPCAPS_TEXGEN;
                                  /* FIXME: Add 
				     D3DVTXPCAPS_LOCALVIEWER 
				     D3DVTXPCAPS_TWEENING */
665 666 667

    pCaps->MaxPrimitiveCount = 0xFFFFFFFF;
    pCaps->MaxVertexIndex = 0xFFFFFFFF;
668
    pCaps->MaxStreams = MAX_STREAMS;
669 670
    pCaps->MaxStreamStride = 1024;

Raphael Junqueira's avatar
Raphael Junqueira committed
671
#if 1
672
    pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
673
    pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS;
Raphael Junqueira's avatar
Raphael Junqueira committed
674 675 676 677
#else
    pCaps->VertexShaderVersion = 0;
    pCaps->MaxVertexShaderConst = D3D8_VSHADER_MAX_CONSTANTS;
#endif
678

679
#if 0
680
    pCaps->PixelShaderVersion = D3DPS_VERSION(1,1);
681
    pCaps->MaxPixelShaderValue = 1.0;
682 683 684 685
#else
    pCaps->PixelShaderVersion = 0;
    pCaps->MaxPixelShaderValue = 0.0;
#endif
686

687 688 689 690 691 692
    /* If we created a dummy context, throw it away */
    if (created) {
        glXMakeCurrent(display, None, NULL);
        glXDestroyContext(display, gl_context);
        LEAVE_GL();
    }
693 694 695
    return D3D_OK;
}

696
HMONITOR WINAPI  IDirect3D8Impl_GetAdapterMonitor(LPDIRECT3D8 iface, UINT Adapter) {
697 698 699 700 701
    ICOM_THIS(IDirect3D8Impl,iface);
    FIXME("(%p)->(Adptr:%d)\n", This, Adapter);
    return D3D_OK;
}

702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719

static void IDirect3D8Impl_FillGLCaps(LPDIRECT3D8 iface, Display* display) {
    const char *GL_Extensions = NULL;
    const char *GLX_Extensions = NULL;
    GLint gl_max;
    ICOM_THIS(IDirect3D8Impl,iface);

    /* 
     * Initialize openGL extension related variables
     *  with Default values 
     */
    memset(&This->gl_info.supported, 0, sizeof(This->gl_info.supported));
    This->gl_info.max_textures   = 1;
    This->gl_info.ps_arb_version = PS_VERSION_NOT_SUPPORTED;
    This->gl_info.vs_arb_version = VS_VERSION_NOT_SUPPORTED;
    This->gl_info.vs_nv_version  = VS_VERSION_NOT_SUPPORTED;
    This->gl_info.vs_ati_version = VS_VERSION_NOT_SUPPORTED;

720 721 722 723
#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = NULL;
    GL_EXT_FUNCS_GEN;
#undef USE_GL_FUNC

724 725 726 727 728 729
    /* Retrieve opengl defaults */
    glGetIntegerv(GL_MAX_CLIP_PLANES, &gl_max);
    This->gl_info.max_clipplanes = min(MAX_CLIPPLANES, gl_max);
    TRACE("ClipPlanes support - num Planes=%d\n", gl_max);

    glGetIntegerv(GL_MAX_LIGHTS, &gl_max);
730
    This->gl_info.max_lights = gl_max;
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
    TRACE("Lights support - max lights=%d\n", gl_max);

    /* Parse the gl supported features, in theory enabling parts of our code appropriately */
    GL_Extensions = glGetString(GL_EXTENSIONS);
    FIXME("GL_Extensions reported:\n");  
    
    if (NULL == GL_Extensions) {
      ERR("   GL_Extensions returns NULL\n");      
    } else {
      while (*GL_Extensions != 0x00) {
        const char *Start = GL_Extensions;
        char ThisExtn[256];

        memset(ThisExtn, 0x00, sizeof(ThisExtn));
        while (*GL_Extensions != ' ' && *GL_Extensions != 0x00) {
	  GL_Extensions++;
        }
        memcpy(ThisExtn, Start, (GL_Extensions - Start));
        FIXME("- %s\n", ThisExtn);

	/**
	 * ARB 
	 */
	if (strcmp(ThisExtn, "GL_ARB_fragment_program") == 0) {
	  This->gl_info.ps_arb_version = PS_VERSION_11;
	  FIXME(" FOUND: ARB Pixel Shader support - version=%02x\n", This->gl_info.ps_arb_version);
	  This->gl_info.supported[ARB_FRAGMENT_PROGRAM] = TRUE;
        } else if (strcmp(ThisExtn, "GL_ARB_multisample") == 0) {
	  FIXME(" FOUND: ARB Multisample support\n");
	  This->gl_info.supported[ARB_MULTISAMPLE] = TRUE;
	} else if (strcmp(ThisExtn, "GL_ARB_multitexture") == 0) {
	  glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &gl_max);
	  FIXME(" FOUND: ARB Multitexture support - GL_MAX_TEXTURE_UNITS_ARB=%u\n", gl_max);
	  This->gl_info.supported[ARB_MULTITEXTURE] = TRUE;
	  This->gl_info.max_textures = min(8, gl_max);
        } else if (strcmp(ThisExtn, "GL_ARB_texture_cube_map") == 0) {
	  FIXME(" FOUND: ARB Texture Cube Map support\n");
	  This->gl_info.supported[ARB_TEXTURE_CUBE_MAP] = TRUE;
        } else if (strcmp(ThisExtn, "GL_ARB_texture_compression") == 0) {
	  FIXME(" FOUND: ARB Texture Compression support\n");
	  This->gl_info.supported[ARB_TEXTURE_COMPRESSION] = TRUE;
772 773 774
        } else if (strcmp(ThisExtn, "GL_ARB_texture_env_combine") == 0) {
	  FIXME(" FOUND: EXT Texture Env combine support\n");
	  This->gl_info.supported[ARB_TEXTURE_ENV_COMBINE] = TRUE;
775
        } else if (strcmp(ThisExtn, "GL_ARB_texture_env_dot3") == 0) {
776 777 778 779
	  if (FALSE == This->gl_info.supported[ARB_TEXTURE_ENV_DOT3]) {
	    FIXME(" FOUND: EXT Dot3 support\n");
	    This->gl_info.supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
	  }
780 781 782 783 784 785 786 787 788 789 790
	} else if (strstr(ThisExtn, "GL_ARB_vertex_program")) {
	  This->gl_info.vs_arb_version = VS_VERSION_11;
	  FIXME(" FOUND: ARB Vertex Shader support - version=%02x\n", This->gl_info.vs_arb_version);
	  This->gl_info.supported[ARB_VERTEX_PROGRAM] = TRUE;

	/**
	 * EXT
	 */
        } else if (strcmp(ThisExtn, "GL_EXT_fog_coord") == 0) {
	  FIXME(" FOUND: EXT Fog coord support\n");
	  This->gl_info.supported[EXT_FOG_COORD] = TRUE;
791
        } else if (strcmp(ThisExtn, "GL_EXT_paletted_texture") == 0) { /* handle paletted texture extensions */
792 793
	  FIXME(" FOUND: EXT Paletted texture support\n");
	  This->gl_info.supported[EXT_PALETTED_TEXTURE] = TRUE;
794 795 796
        } else if (strcmp(ThisExtn, "GL_EXT_point_parameters") == 0) {
	  FIXME(" FOUND: EXT Point parameters support\n");
	  This->gl_info.supported[EXT_POINT_PARAMETERS] = TRUE;
797 798 799
	} else if (strcmp(ThisExtn, "GL_EXT_secondary_color") == 0) {
	  FIXME(" FOUND: EXT Secondary coord support\n");
	  This->gl_info.supported[EXT_SECONDARY_COLOR] = TRUE;
800
#if defined(GL_EXT_texture_compression_s3tc)
801 802 803
	} 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;
804
#endif
805 806 807 808 809
        } 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");
	    This->gl_info.supported[ARB_TEXTURE_ENV_DOT3] = TRUE;
	  }
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
	} else if (strcmp(ThisExtn, "GL_EXT_texture_filter_anisotropic") == 0) {
	  FIXME(" FOUND: EXT Texture Anisotropic filter support\n");
	  This->gl_info.supported[EXT_TEXTURE_FILTER_ANISOTROPIC] = TRUE;
	} else if (strcmp(ThisExtn, "GL_EXT_texture_lod") == 0) {
	  FIXME(" FOUND: EXT Texture LOD support\n");
	  This->gl_info.supported[EXT_TEXTURE_LOD] = TRUE;
	} else if (strcmp(ThisExtn, "GL_EXT_texture_lod_bias") == 0) {
	  FIXME(" FOUND: EXT Texture LOD bias support\n");
	  This->gl_info.supported[EXT_TEXTURE_LOD_BIAS] = TRUE;
	} else if (strcmp(ThisExtn, "GL_EXT_vertex_weighting") == 0) {
	  FIXME(" FOUND: EXT Vertex weighting support\n");
	  This->gl_info.supported[EXT_VERTEX_WEIGHTING] = TRUE;

	/**
	 * NVIDIA 
	 */
	} else if (strstr(ThisExtn, "GL_NV_fragment_program")) {
	  This->gl_info.ps_nv_version = PS_VERSION_11;
	  FIXME(" FOUND: NVIDIA (NV) Pixel Shader support - version=%02x\n", This->gl_info.ps_nv_version);
	  This->gl_info.supported[NV_FRAGMENT_PROGRAM] = TRUE;
	} else if (strstr(ThisExtn, "GL_NV_vertex_program")) {
	  This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program1_1")) ? VS_VERSION_11 : VS_VERSION_10);
	  This->gl_info.vs_nv_version = max(This->gl_info.vs_nv_version, (0 == strcmp(ThisExtn, "GL_NV_vertex_program2"))   ? VS_VERSION_20 : VS_VERSION_10);
	  FIXME(" FOUND: NVIDIA (NV) Vertex Shader support - version=%02x\n", This->gl_info.vs_nv_version);
	  This->gl_info.supported[NV_VERTEX_PROGRAM] = TRUE;

	/**
	 * ATI
	 */
	/** TODO */
	} else if (strcmp(ThisExtn, "GL_EXT_vertex_shader") == 0) {
	  This->gl_info.vs_ati_version = VS_VERSION_11;
	  FIXME(" FOUND: ATI (EXT) Vertex Shader support - version=%02x\n", This->gl_info.vs_ati_version);
	  This->gl_info.supported[EXT_VERTEX_SHADER] = TRUE;
	}


        if (*GL_Extensions == ' ') GL_Extensions++;
      }
    }

851 852 853 854
#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
    GL_EXT_FUNCS_GEN;
#undef USE_GL_FUNC

855 856 857
    if (display != NULL) {
        GLX_Extensions = glXQueryExtensionsString(display, DefaultScreen(display));
        FIXME("GLX_Extensions reported:\n");  
858
    
859 860 861 862 863 864 865 866 867 868 869 870 871 872 873
        if (NULL == GLX_Extensions) {
          ERR("   GLX_Extensions returns NULL\n");      
        } else {
          while (*GLX_Extensions != 0x00) {
            const char *Start = GLX_Extensions;
            char ThisExtn[256];
           
            memset(ThisExtn, 0x00, sizeof(ThisExtn));
            while (*GLX_Extensions != ' ' && *GLX_Extensions != 0x00) {
              GLX_Extensions++;
            }
            memcpy(ThisExtn, Start, (GLX_Extensions - Start));
            FIXME("- %s\n", ThisExtn);
            if (*GLX_Extensions == ' ') GLX_Extensions++;
          }
874 875
        }
    }
876 877 878 879 880

#define USE_GL_FUNC(type, pfn) This->gl_info.pfn = (type) glXGetProcAddressARB(#pfn);
    GLX_EXT_FUNCS_GEN;
#undef USE_GL_FUNC

881 882 883
    /* Only save the values obtained when a display is provided */
    if (display != NULL) This->isGLInfoValid = TRUE;

884 885
}

886 887 888 889 890 891
HRESULT  WINAPI  IDirect3D8Impl_CreateDevice               (LPDIRECT3D8 iface,
                                                            UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow,
                                                            DWORD BehaviourFlags, D3DPRESENT_PARAMETERS* pPresentationParameters,
                                                            IDirect3DDevice8** ppReturnedDeviceInterface) {
    IDirect3DDevice8Impl *object;
    HWND whichHWND;
892 893
    int num;
    XVisualInfo template;
894 895

    ICOM_THIS(IDirect3D8Impl,iface);
896
    TRACE("(%p)->(Adptr:%d, DevType: %x, FocusHwnd: %p, BehFlags: %lx, PresParms: %p, RetDevInt: %p)\n", This, Adapter, DeviceType,
897 898 899 900
          hFocusWindow, BehaviourFlags, pPresentationParameters, ppReturnedDeviceInterface);

    /* Allocate the storage for the device */
    object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
901 902 903
    if (NULL == object) {
      return D3DERR_OUTOFVIDEOMEMORY;
    }
904 905 906
    object->lpVtbl = &Direct3DDevice8_Vtbl;
    object->ref = 1;
    object->direct3d8 = This;
907 908
    /** The device AddRef the direct3d8 Interface else crash in propers clients codes */
    IDirect3D8_AddRef((LPDIRECT3D8) object->direct3d8);
909 910 911 912 913

    /** use StateBlock Factory here, for creating the startup stateBlock */
    object->StateBlock = NULL;
    IDirect3DDeviceImpl_CreateStateBlock(object, D3DSBT_ALL, NULL);
    object->UpdateStateBlock = object->StateBlock;
914 915 916 917 918 919 920

    /* Save the creation parameters */
    object->CreateParms.AdapterOrdinal = Adapter;
    object->CreateParms.DeviceType = DeviceType;
    object->CreateParms.hFocusWindow = hFocusWindow;
    object->CreateParms.BehaviorFlags = BehaviourFlags;

921
    *ppReturnedDeviceInterface = (LPDIRECT3DDEVICE8) object;
922 923 924 925 926 927 928 929 930

    /* Initialize settings */
    object->PresentParms.BackBufferCount = 1; /* Opengl only supports one? */
    object->adapterNo = Adapter;
    object->devType = DeviceType;

    /* Initialize openGl */
    {
        HDC hDc;
931 932 933 934 935
	/*int dblBuf[] = {GLX_STENCIL_SIZE,8,GLX_RGBA,GLX_DEPTH_SIZE,16,GLX_DOUBLEBUFFER,None};*/
        int dblBuf[] = {GLX_RGBA, 
			GLX_STENCIL_SIZE, 8, /*  2 */
			GLX_DEPTH_SIZE,  16, /*  4 */
			GLX_DOUBLEBUFFER, None};
936
        /* FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat */
937 938 939 940 941 942 943

        /* Which hwnd are we using? */
/*      if (pPresentationParameters->Windowed) { */
           whichHWND = pPresentationParameters->hDeviceWindow;
           if (!whichHWND) {
               whichHWND = hFocusWindow;
           }
944
	   object->win_handle = whichHWND;
945 946 947 948 949 950 951 952 953 954 955 956
           object->win     = (Window)GetPropA( whichHWND, "__wine_x11_client_window" );
/*
 *      } else {
 *           whichHWND       = (HWND) GetDesktopWindow();
 *           object->win     = (Window)GetPropA(whichHWND, "__wine_x11_whole_window" );
 *	   root_window
 *        }
 */

        hDc = GetDC(whichHWND);
        object->display = get_display(hDc);

957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989

	TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This, 
	      pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
	      pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));

	
#if 0
	if (TRUE == pPresentationParameters->EnableAutoDepthStencil) {
	  switch (pPresentationParameters->AutoDepthStencilFormat) {
	  case D3DFMT_D16_LOCKABLE: dblBuf[2] =  8; dblBuf[4] = 16; break;
	  case D3DFMT_D16:          dblBuf[2] =  8; dblBuf[4] = 16; break;
	  case D3DFMT_D15S1:        dblBuf[2] =  1; dblBuf[4] = 16; break;
	  case D3DFMT_D24X4S4:      dblBuf[2] =  4; dblBuf[4] = 24; break;
	  case D3DFMT_D24S8:        dblBuf[2] =  8; dblBuf[4] = 24; break;
	  case D3DFMT_D24X8:        dblBuf[2] =  8; dblBuf[4] = 24; break;
	  case D3DFMT_D32:          dblBuf[2] =  8; dblBuf[4] = 32; break;
	  default:                  dblBuf[2] =  8; dblBuf[4] = 16; break;
	  }
	}
	
	switch (pPresentationParameters->BackBufferFormat) {
	case D3DFMT_R3G3B2:   dblBuf[6] = 3; dblBuf[8] = 3; dblBuf[10] = 2; dblBuf[12] = 0; break;
	case D3DFMT_R5G6B5:   dblBuf[6] = 5; dblBuf[8] = 6; dblBuf[10] = 5; dblBuf[12] = 0; break;
	case D3DFMT_X1R5G5B5: dblBuf[6] = 5; dblBuf[8] = 5; dblBuf[10] = 5; dblBuf[12] = 0; break;
	case D3DFMT_A1R5G5B5: dblBuf[6] = 5; dblBuf[8] = 5; dblBuf[10] = 5; dblBuf[12] = 1; break;
	case D3DFMT_X4R4G4B4: dblBuf[6] = 4; dblBuf[8] = 4; dblBuf[10] = 4; dblBuf[12] = 0; break;
	case D3DFMT_R8G8B8:   dblBuf[6] = 8; dblBuf[8] = 8; dblBuf[10] = 8; dblBuf[12] = 0; break;
	case D3DFMT_X8R8G8B8: dblBuf[6] = 8; dblBuf[8] = 8; dblBuf[10] = 8; dblBuf[12] = 0; break;
	case D3DFMT_A8R8G8B8: dblBuf[6] = 8; dblBuf[8] = 8; dblBuf[10] = 8; dblBuf[12] = 8; break;
	default:              dblBuf[6] = 5; dblBuf[8] = 6; dblBuf[10] = 5; dblBuf[12] = 0; break;
	}
#endif

990
        ENTER_GL();
991 992 993 994 995 996 997 998
	object->visInfo = glXChooseVisual(object->display, DefaultScreen(object->display), dblBuf);
	if (NULL == object->visInfo) {
	  FIXME("cannot choose needed glxVisual with Stencil Buffer\n"); 

	  /**
	   * second try using wine initialized visual ...
	   * must be fixed reworking wine-glx init
	   */
999
	  template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1000 1001 1002 1003 1004 1005 1006 1007
	  object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
	  if (NULL == object->visInfo) {
	    ERR("cannot really get XVisual\n"); 
	    LEAVE_GL();
	    return D3DERR_NOTAVAILABLE;
	  }
	}
        object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1008
	if (NULL == object->glCtx) {
1009 1010 1011 1012
	  ERR("cannot create glxContext\n"); 
	  LEAVE_GL();
	  return D3DERR_NOTAVAILABLE;
	}
1013 1014
	LEAVE_GL();

1015
        ReleaseDC(whichHWND, hDc);
1016 1017 1018 1019 1020 1021
    }

    if (object->glCtx == NULL) {
        ERR("Error in context creation !\n");
        return D3DERR_INVALIDCALL;
    } else {
1022
        TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1023
	      whichHWND, object->glCtx, object->win, object->visInfo);
1024 1025
    }

1026 1027 1028
    /* If not windowed, need to go fullscreen, and resize the HWND to the appropriate  */
    /*        dimensions                                                               */
    if (!pPresentationParameters->Windowed) {
1029
#if 1
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
	DEVMODEW devmode;
	HDC hdc;
        int bpp = 0;
	memset(&devmode, 0, sizeof(DEVMODEW));
	devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; 
	MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
        hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
        bpp = GetDeviceCaps(hdc, BITSPIXEL);
        DeleteDC(hdc);
	devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp;/*Stupid XVidMode cannot change bpp D3DFmtGetBpp(object, pPresentationParameters->BackBufferFormat);*/
	devmode.dmPelsWidth  = pPresentationParameters->BackBufferWidth;
	devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
	ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
#else
1044
        FIXME("Requested full screen support not implemented, expect windowed operation\n");
1045
#endif
1046 1047 1048 1049

        /* Make popup window */
        ShowWindow(whichHWND, SW_HIDE);
        SetWindowLongA(whichHWND, GWL_STYLE, WS_POPUP);
1050 1051 1052
        SetWindowPos(object->win_handle, HWND_TOP, 0, 0, 
		     pPresentationParameters->BackBufferWidth,
                     pPresentationParameters->BackBufferHeight, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1053
        ShowWindow(whichHWND, SW_SHOW);
1054 1055
    }

1056 1057 1058 1059 1060
    TRACE("Creating back buffer\n");
    /* MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
       then the corresponding dimension of the client area of the hDeviceWindow
       (or the focus window, if hDeviceWindow is NULL) is taken. */
    if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth  == 0) ||
1061
                                              (pPresentationParameters->BackBufferHeight == 0))) {
1062 1063 1064 1065
        RECT Rect;

        GetClientRect(whichHWND, &Rect);

1066
        if (pPresentationParameters->BackBufferWidth == 0) {
1067 1068 1069
           pPresentationParameters->BackBufferWidth = Rect.right;
           TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
        }
1070
        if (pPresentationParameters->BackBufferHeight == 0) {
1071 1072 1073 1074 1075
           pPresentationParameters->BackBufferHeight = Rect.bottom;
           TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
        }
    }

1076 1077 1078 1079
    /* Save the presentation parms now filled in correctly */
    memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));


1080 1081 1082 1083
    IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
                                            pPresentationParameters->BackBufferWidth,
                                            pPresentationParameters->BackBufferHeight,
                                            pPresentationParameters->BackBufferFormat,
1084 1085
					    pPresentationParameters->MultiSampleType,
					    TRUE,
1086 1087 1088
                                            (LPDIRECT3DSURFACE8*) &object->frontBuffer);

    IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
1089 1090 1091
                                            pPresentationParameters->BackBufferWidth,
                                            pPresentationParameters->BackBufferHeight,
                                            pPresentationParameters->BackBufferFormat,
1092 1093
					    pPresentationParameters->MultiSampleType,
					    TRUE,
1094 1095
                                            (LPDIRECT3DSURFACE8*) &object->backBuffer);

1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
    if (pPresentationParameters->EnableAutoDepthStencil) {
       IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
	  					      pPresentationParameters->BackBufferWidth,
						      pPresentationParameters->BackBufferHeight,
						      pPresentationParameters->AutoDepthStencilFormat,
						      D3DMULTISAMPLE_NONE,
						      (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
    } else {
      object->depthStencilBuffer = NULL;
    }
1106
    TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil @ %p\n",object->frontBuffer, object->backBuffer, object->depthStencilBuffer);
1107 1108 1109 1110 1111 1112 1113

    /* init the default renderTarget management */
    object->drawable = object->win;
    object->render_ctx = object->glCtx;
    object->renderTarget = object->frontBuffer;
    IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->renderTarget);
    object->stencilBufferTarget = object->depthStencilBuffer;
Raphael Junqueira's avatar
Raphael Junqueira committed
1114
    if (NULL != object->stencilBufferTarget) {
1115
      IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) object->stencilBufferTarget);
Raphael Junqueira's avatar
Raphael Junqueira committed
1116
    }
1117

1118
    ENTER_GL();
1119

1120
    if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1121
      ERR("Error in setting current context (context %p drawable %ld)!\n", object->glCtx, object->win);
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133
    }
    checkGLcall("glXMakeCurrent");

    /* Clear the screen */
    glClearColor(1.0, 0.0, 0.0, 0.0);
    checkGLcall("glClearColor");
    glColor3f(1.0, 1.0, 1.0);
    checkGLcall("glColor3f");

    glEnable(GL_LIGHTING);
    checkGLcall("glEnable");

1134 1135 1136
    glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
    checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");

1137
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1138
    checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1139

Raphael Junqueira's avatar
Raphael Junqueira committed
1140 1141
    glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
    checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1142

1143 1144 1145 1146
    /* 
     * Initialize openGL extension related variables
     *  with Default values 
     */
1147
    IDirect3D8Impl_FillGLCaps(iface, object->display);
1148

1149
    /* Setup all the devices defaults */
1150
    IDirect3DDeviceImpl_InitStartupStateBlock(object);
1151

1152
    LEAVE_GL();
1153

1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
    { /* Set a default viewport */
       D3DVIEWPORT8 vp;
       vp.X      = 0;
       vp.Y      = 0;
       vp.Width  = pPresentationParameters->BackBufferWidth;
       vp.Height = pPresentationParameters->BackBufferHeight;
       vp.MinZ   = 0.0f;
       vp.MaxZ   = 1.0f;
       IDirect3DDevice8Impl_SetViewport((LPDIRECT3DDEVICE8) object, &vp);
    }

1165 1166 1167 1168 1169
    /* Initialize the current view state */
    object->modelview_valid = 1;
    object->proj_valid = 0;
    object->view_ident = 1;
    object->last_was_rhw = 0;
1170
    glGetIntegerv(GL_MAX_LIGHTS, &object->maxConcurrentLights);
1171
    TRACE("(%p,%d) All defaults now set up, leaving CreateDevice with %p\n", This, Adapter, object);
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
    return D3D_OK;
}

ICOM_VTABLE(IDirect3D8) Direct3D8_Vtbl =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    IDirect3D8Impl_QueryInterface,
    IDirect3D8Impl_AddRef,
    IDirect3D8Impl_Release,
    IDirect3D8Impl_RegisterSoftwareDevice,
    IDirect3D8Impl_GetAdapterCount,
    IDirect3D8Impl_GetAdapterIdentifier,
    IDirect3D8Impl_GetAdapterModeCount,
    IDirect3D8Impl_EnumAdapterModes,
    IDirect3D8Impl_GetAdapterDisplayMode,
    IDirect3D8Impl_CheckDeviceType,
    IDirect3D8Impl_CheckDeviceFormat,
    IDirect3D8Impl_CheckDeviceMultiSampleType,
    IDirect3D8Impl_CheckDepthStencilMatch,
    IDirect3D8Impl_GetDeviceCaps,
    IDirect3D8Impl_GetAdapterMonitor,
    IDirect3D8Impl_CreateDevice
};