зеркало из https://github.com/mozilla/moz-skia.git
Add SkWGLExtensionInterface for dealing with WGL extensions
Review URL: http://codereview.appspot.com/5447059 git-svn-id: http://skia.googlecode.com/svn/trunk@2777 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
06711bd972
Коммит
bd7c64150c
|
@ -36,6 +36,7 @@
|
|||
'../include/utils/SkSfntUtils.h',
|
||||
'../include/utils/SkTextBox.h',
|
||||
'../include/utils/SkUnitMappers.h',
|
||||
'../include/utils/SkWGL.h',
|
||||
|
||||
'../src/utils/SkBoundaryPatch.cpp',
|
||||
'../src/utils/SkCamera.cpp',
|
||||
|
@ -77,7 +78,8 @@
|
|||
'../src/utils/win/skia_win.cpp',
|
||||
'../src/utils/win/SkHRESULT.cpp',
|
||||
'../src/utils/win/SkIStream.cpp',
|
||||
'../src/utils/win/SkOSWindow_Win.cpp',
|
||||
'../src/utils/win/SkOSWindow_win.cpp',
|
||||
'../src/utils/win/SkWGL_win.cpp',
|
||||
],
|
||||
'sources!': [
|
||||
'../src/utils/SDL/SkOSWindow_SDL.cpp',
|
||||
|
@ -131,16 +133,15 @@
|
|||
'include_dirs!': [
|
||||
'../include/utils/win',
|
||||
],
|
||||
'sources/': [ ['exclude', '_win.(h|cpp)$'],],
|
||||
'sources!': [
|
||||
'../include/utils/win/SkAutoCoInitialize.h',
|
||||
'../include/utils/win/SkHRESULT.h',
|
||||
'../include/utils/win/SkIStream.h',
|
||||
'../include/utils/win/SkTScopedComPtr.h',
|
||||
'../src/utils/win/SkAutoCoInitialize.cpp',
|
||||
'../src/utils/win/skia_win.cpp',
|
||||
'../src/utils/win/SkHRESULT.cpp',
|
||||
'../src/utils/win/SkIStream.cpp',
|
||||
'../src/utils/win/SkOSWindow_Win.cpp',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
#ifndef SkWGL_DEFINED
|
||||
#define SkWGL_DEFINED
|
||||
|
||||
/**
|
||||
* Working with WGL extensions can be a pain. Among the reasons is that You must
|
||||
* have a GL context to get the proc addresses, but you want to use the procs to
|
||||
* create a context in the first place. So you have to create a dummy GL ctx to
|
||||
* get the proc addresses.
|
||||
*
|
||||
* This file helps by providing SkCreateWGLInterface(). It returns a struct of
|
||||
* function pointers that it initializes. It also has a helper function to query
|
||||
* for WGL extensions. It handles the fact that wglGetExtensionsString is itself
|
||||
* an extension.
|
||||
*/
|
||||
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define SK_LOCAL_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <Windows.h>
|
||||
#if defined(SK_LOCAL_LEAN_AND_MEAN)
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#undef SK_LOCAL_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#define SK_WGL_DRAW_TO_WINDOW_ARB 0x2001
|
||||
#define SK_WGL_ACCELERATION_ARB 0x2003
|
||||
#define SK_WGL_SUPPORT_OPENGL_ARB 0x2010
|
||||
#define SK_WGL_DOUBLE_BUFFER_ARB 0x2011
|
||||
#define SK_WGL_COLOR_BITS_ARB 0x2014
|
||||
#define SK_WGL_ALPHA_BITS_ARB 0x201B
|
||||
#define SK_WGL_STENCIL_BITS_ARB 0x2023
|
||||
#define SK_WGL_FULL_ACCELERATION_ARB 0x2027
|
||||
#define SK_WGL_SAMPLE_BUFFERS_ARB 0x2041
|
||||
#define SK_WGL_SAMPLES_ARB 0x2042
|
||||
#define SK_WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||
#define SK_WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||
#define SK_WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
|
||||
#define SK_WGL_CONTEXT_FLAGS_ARB 0x2094
|
||||
#define SK_WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||
#define SK_WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
|
||||
#define SK_WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
|
||||
#define SK_WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||
#define SK_WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||
#define SK_WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
|
||||
#define SK_ERROR_INVALID_VERSION_ARB 0x2095
|
||||
#define SK_ERROR_INVALID_PROFILE_ARB 0x2096
|
||||
|
||||
class SkWGLExtensions {
|
||||
public:
|
||||
SkWGLExtensions();
|
||||
/**
|
||||
* Determines if an extensions is available for a given DC.
|
||||
* WGL_ARB_extensions_string is considered a prerequisite for all other
|
||||
* extensions. It is necessary to check this before calling other class
|
||||
* functions.
|
||||
*/
|
||||
bool hasExtension(HDC dc, const char* ext) const;
|
||||
|
||||
const char* getExtensionsString(HDC hdc) const;
|
||||
BOOL choosePixelFormat(HDC hdc, const int*, const FLOAT*, UINT, int*, UINT*) const;
|
||||
BOOL getPixelFormatAttribiv(HDC, int, int, UINT, const int*, int*) const;
|
||||
BOOL getPixelFormatAttribfv(HDC hdc, int, int, UINT, const int*, FLOAT*) const;
|
||||
HGLRC createContextAttribs(HDC, HGLRC, const int *) const;
|
||||
|
||||
private:
|
||||
typedef const char* (WINAPI *GetExtensionsStringProc)(HDC hdc);
|
||||
typedef BOOL (WINAPI *ChoosePixelFormatProc)(HDC hdc, const int *, const FLOAT *, UINT, int *, UINT *);
|
||||
typedef BOOL (WINAPI *GetPixelFormatAttribivProc)(HDC, int, int, UINT, const int*, int*);
|
||||
typedef BOOL (WINAPI *GetPixelFormatAttribfvProc)(HDC hdc, int, int, UINT, const int*, FLOAT*);
|
||||
typedef HGLRC (WINAPI *CreateContextAttribsProc)(HDC hDC, HGLRC, const int *);
|
||||
|
||||
GetExtensionsStringProc fGetExtensionsString;
|
||||
ChoosePixelFormatProc fChoosePixelFormat;
|
||||
GetPixelFormatAttribfvProc fGetPixelFormatAttribfv;
|
||||
GetPixelFormatAttribivProc fGetPixelFormatAttribiv;
|
||||
CreateContextAttribsProc fCreateContextAttribs;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,492 @@
|
|||
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "SkTypes.h"
|
||||
|
||||
#if defined(SK_BUILD_FOR_WIN)
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <d3d9.h>
|
||||
#include <WindowsX.h>
|
||||
#include "SkWGL.h"
|
||||
#include "SkWindow.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkOSMenu.h"
|
||||
#include "SkTime.h"
|
||||
#include "SkUtils.h"
|
||||
|
||||
#include "SkGraphics.h"
|
||||
|
||||
#define INVALIDATE_DELAY_MS 200
|
||||
|
||||
static SkOSWindow* gCurrOSWin;
|
||||
static HWND gEventTarget;
|
||||
|
||||
#define WM_EVENT_CALLBACK (WM_USER+0)
|
||||
|
||||
void post_skwinevent()
|
||||
{
|
||||
PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
|
||||
}
|
||||
|
||||
SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd),
|
||||
fHGLRC(NULL),
|
||||
fGLAttached(false),
|
||||
fD3D9Device(NULL),
|
||||
fD3D9Attached(FALSE) {
|
||||
gEventTarget = (HWND)hWnd;
|
||||
}
|
||||
|
||||
SkOSWindow::~SkOSWindow() {
|
||||
if (NULL != fD3D9Device) {
|
||||
((IDirect3DDevice9*)fD3D9Device)->Release();
|
||||
}
|
||||
if (NULL != fHGLRC) {
|
||||
wglDeleteContext((HGLRC)fHGLRC);
|
||||
}
|
||||
}
|
||||
|
||||
static SkKey winToskKey(WPARAM vk) {
|
||||
static const struct {
|
||||
WPARAM fVK;
|
||||
SkKey fKey;
|
||||
} gPair[] = {
|
||||
{ VK_BACK, kBack_SkKey },
|
||||
{ VK_CLEAR, kBack_SkKey },
|
||||
{ VK_RETURN, kOK_SkKey },
|
||||
{ VK_UP, kUp_SkKey },
|
||||
{ VK_DOWN, kDown_SkKey },
|
||||
{ VK_LEFT, kLeft_SkKey },
|
||||
{ VK_RIGHT, kRight_SkKey }
|
||||
};
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
|
||||
if (gPair[i].fVK == vk) {
|
||||
return gPair[i].fKey;
|
||||
}
|
||||
}
|
||||
return kNONE_SkKey;
|
||||
}
|
||||
|
||||
bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
switch (message) {
|
||||
case WM_KEYDOWN: {
|
||||
SkKey key = winToskKey(wParam);
|
||||
if (kNONE_SkKey != key) {
|
||||
this->handleKey(key);
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
case WM_KEYUP: {
|
||||
SkKey key = winToskKey(wParam);
|
||||
if (kNONE_SkKey != key) {
|
||||
this->handleKeyUp(key);
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
case WM_UNICHAR:
|
||||
this->handleChar(wParam);
|
||||
return true;
|
||||
case WM_CHAR: {
|
||||
this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
|
||||
return true;
|
||||
} break;
|
||||
case WM_SIZE:
|
||||
this->resize(lParam & 0xFFFF, lParam >> 16);
|
||||
break;
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hWnd, &ps);
|
||||
this->doPaint(hdc);
|
||||
EndPaint(hWnd, &ps);
|
||||
return true;
|
||||
} break;
|
||||
|
||||
case WM_TIMER: {
|
||||
RECT* rect = (RECT*)wParam;
|
||||
InvalidateRect(hWnd, rect, FALSE);
|
||||
KillTimer(hWnd, (UINT_PTR)rect);
|
||||
delete rect;
|
||||
return true;
|
||||
} break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
|
||||
return true;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
|
||||
return true;
|
||||
|
||||
case WM_LBUTTONUP:
|
||||
this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
|
||||
return true;
|
||||
|
||||
case WM_EVENT_CALLBACK:
|
||||
if (SkEvent::ProcessEvent()) {
|
||||
post_skwinevent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SkOSWindow::doPaint(void* ctx) {
|
||||
this->update(NULL);
|
||||
|
||||
if (!fGLAttached && !fD3D9Attached)
|
||||
{
|
||||
HDC hdc = (HDC)ctx;
|
||||
const SkBitmap& bitmap = this->getBitmap();
|
||||
|
||||
BITMAPINFO bmi;
|
||||
memset(&bmi, 0, sizeof(bmi));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = bitmap.width();
|
||||
bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = 0;
|
||||
|
||||
//
|
||||
// Do the SetDIBitsToDevice.
|
||||
//
|
||||
// TODO(wjmaclean):
|
||||
// Fix this call to handle SkBitmaps that have rowBytes != width,
|
||||
// i.e. may have padding at the end of lines. The SkASSERT below
|
||||
// may be ignored by builds, and the only obviously safe option
|
||||
// seems to be to copy the bitmap to a temporary (contiguous)
|
||||
// buffer before passing to SetDIBitsToDevice().
|
||||
SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
|
||||
bitmap.lockPixels();
|
||||
int iRet = SetDIBitsToDevice(hdc,
|
||||
0, 0,
|
||||
bitmap.width(), bitmap.height(),
|
||||
0, 0,
|
||||
0, bitmap.height(),
|
||||
bitmap.getPixels(),
|
||||
&bmi,
|
||||
DIB_RGB_COLORS);
|
||||
bitmap.unlockPixels();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void SkOSWindow::updateSize()
|
||||
{
|
||||
RECT r;
|
||||
GetWindowRect((HWND)this->getHWND(), &r);
|
||||
this->resize(r.right - r.left, r.bottom - r.top);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SkOSWindow::onHandleInval(const SkIRect& r) {
|
||||
RECT* rect = new RECT;
|
||||
rect->left = r.fLeft;
|
||||
rect->top = r.fTop;
|
||||
rect->right = r.fRight;
|
||||
rect->bottom = r.fBottom;
|
||||
SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
|
||||
}
|
||||
|
||||
void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
|
||||
{
|
||||
}
|
||||
|
||||
void SkOSWindow::onSetTitle(const char title[]){
|
||||
SetWindowTextA((HWND)fHWND, title);
|
||||
}
|
||||
|
||||
enum {
|
||||
SK_MacReturnKey = 36,
|
||||
SK_MacDeleteKey = 51,
|
||||
SK_MacEndKey = 119,
|
||||
SK_MacLeftKey = 123,
|
||||
SK_MacRightKey = 124,
|
||||
SK_MacDownKey = 125,
|
||||
SK_MacUpKey = 126,
|
||||
|
||||
SK_Mac0Key = 0x52,
|
||||
SK_Mac1Key = 0x53,
|
||||
SK_Mac2Key = 0x54,
|
||||
SK_Mac3Key = 0x55,
|
||||
SK_Mac4Key = 0x56,
|
||||
SK_Mac5Key = 0x57,
|
||||
SK_Mac6Key = 0x58,
|
||||
SK_Mac7Key = 0x59,
|
||||
SK_Mac8Key = 0x5b,
|
||||
SK_Mac9Key = 0x5c
|
||||
};
|
||||
|
||||
static SkKey raw2key(uint32_t raw)
|
||||
{
|
||||
static const struct {
|
||||
uint32_t fRaw;
|
||||
SkKey fKey;
|
||||
} gKeys[] = {
|
||||
{ SK_MacUpKey, kUp_SkKey },
|
||||
{ SK_MacDownKey, kDown_SkKey },
|
||||
{ SK_MacLeftKey, kLeft_SkKey },
|
||||
{ SK_MacRightKey, kRight_SkKey },
|
||||
{ SK_MacReturnKey, kOK_SkKey },
|
||||
{ SK_MacDeleteKey, kBack_SkKey },
|
||||
{ SK_MacEndKey, kEnd_SkKey },
|
||||
{ SK_Mac0Key, k0_SkKey },
|
||||
{ SK_Mac1Key, k1_SkKey },
|
||||
{ SK_Mac2Key, k2_SkKey },
|
||||
{ SK_Mac3Key, k3_SkKey },
|
||||
{ SK_Mac4Key, k4_SkKey },
|
||||
{ SK_Mac5Key, k5_SkKey },
|
||||
{ SK_Mac6Key, k6_SkKey },
|
||||
{ SK_Mac7Key, k7_SkKey },
|
||||
{ SK_Mac8Key, k8_SkKey },
|
||||
{ SK_Mac9Key, k9_SkKey }
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
|
||||
if (gKeys[i].fRaw == raw)
|
||||
return gKeys[i].fKey;
|
||||
return kNONE_SkKey;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkEvent::SignalNonEmptyQueue()
|
||||
{
|
||||
post_skwinevent();
|
||||
//SkDebugf("signal nonempty\n");
|
||||
}
|
||||
|
||||
static UINT_PTR gTimer;
|
||||
|
||||
VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||
{
|
||||
SkEvent::ServiceQueueTimer();
|
||||
//SkDebugf("timer task fired\n");
|
||||
}
|
||||
|
||||
void SkEvent::SignalQueueTimer(SkMSec delay)
|
||||
{
|
||||
if (gTimer)
|
||||
{
|
||||
KillTimer(NULL, gTimer);
|
||||
gTimer = NULL;
|
||||
}
|
||||
if (delay)
|
||||
{
|
||||
gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
|
||||
//SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define USE_MSAA 0
|
||||
|
||||
HGLRC create_gl(HWND hwnd) {
|
||||
HDC dc = GetDC(hwnd);
|
||||
SkWGLExtensions extensions;
|
||||
if (!extensions.hasExtension(dc, "WGL_ARB_pixel_format")) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HDC prevDC = wglGetCurrentDC();
|
||||
HGLRC prevGLRC = wglGetCurrentContext();
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
|
||||
int format = 0;
|
||||
|
||||
GLint iattrs[] = {
|
||||
SK_WGL_DRAW_TO_WINDOW_ARB, TRUE,
|
||||
SK_WGL_DOUBLE_BUFFER_ARB, TRUE,
|
||||
SK_WGL_ACCELERATION_ARB, SK_WGL_FULL_ACCELERATION_ARB,
|
||||
SK_WGL_SUPPORT_OPENGL_ARB, TRUE,
|
||||
SK_WGL_COLOR_BITS_ARB, 24,
|
||||
SK_WGL_ALPHA_BITS_ARB, 8,
|
||||
SK_WGL_STENCIL_BITS_ARB, 8,
|
||||
|
||||
// these must be kept last
|
||||
SK_WGL_SAMPLE_BUFFERS_ARB, TRUE,
|
||||
SK_WGL_SAMPLES_ARB, 0,
|
||||
0,0
|
||||
};
|
||||
static const int kSampleBuffersValueIdx = SK_ARRAY_COUNT(iattrs) - 5;
|
||||
static const int kSamplesValueIdx = SK_ARRAY_COUNT(iattrs) - 3;
|
||||
if (USE_MSAA && extensions.hasExtension(dc, "WGL_ARB_multisample")) {
|
||||
for (int samples = 16; samples > 1; --samples) {
|
||||
|
||||
iattrs[kSamplesValueIdx] = samples;
|
||||
GLfloat fattrs[] = {0,0};
|
||||
GLuint num;
|
||||
int formats[64];
|
||||
extensions.choosePixelFormat(dc, iattrs, fattrs, 64, formats, &num);
|
||||
num = min(num,64);
|
||||
for (GLuint i = 0; i < num; ++i) {
|
||||
DescribePixelFormat(dc, formats[i], sizeof(pfd), &pfd);
|
||||
if (SetPixelFormat(dc, formats[i], &pfd)) {
|
||||
format = formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0 == format) {
|
||||
iattrs[kSampleBuffersValueIdx-1] = iattrs[kSampleBuffersValueIdx] = 0;
|
||||
iattrs[kSamplesValueIdx-1] = iattrs[kSamplesValueIdx] = 0;
|
||||
GLfloat fattrs[] = {0,0};
|
||||
GLuint num;
|
||||
extensions.choosePixelFormat(dc, iattrs, fattrs, 1, &format, &num);
|
||||
DescribePixelFormat(dc, format, sizeof(pfd), &pfd);
|
||||
BOOL set = SetPixelFormat(dc, format, &pfd);
|
||||
SkASSERT(TRUE == set);
|
||||
}
|
||||
|
||||
HGLRC glrc = wglCreateContext(dc);
|
||||
SkASSERT(glrc);
|
||||
|
||||
wglMakeCurrent(prevDC, prevGLRC);
|
||||
return glrc;
|
||||
}
|
||||
|
||||
bool SkOSWindow::attachGL() {
|
||||
if (NULL == fHGLRC) {
|
||||
fHGLRC = create_gl((HWND)fHWND);
|
||||
if (NULL == fHGLRC) {
|
||||
return false;
|
||||
}
|
||||
glClearStencil(0);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glStencilMask(0xffffffff);
|
||||
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
|
||||
glViewport(0, 0, SkScalarRound(this->width()),
|
||||
SkScalarRound(this->height()));
|
||||
fGLAttached = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SkOSWindow::detachGL() {
|
||||
wglMakeCurrent(GetDC((HWND)fHWND), 0);
|
||||
fGLAttached = false;
|
||||
}
|
||||
|
||||
void SkOSWindow::presentGL() {
|
||||
glFlush();
|
||||
SwapBuffers(GetDC((HWND)fHWND));
|
||||
}
|
||||
|
||||
IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
|
||||
HRESULT hr;
|
||||
|
||||
IDirect3D9* d3d9;
|
||||
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
if (NULL == d3d9) {
|
||||
return NULL;
|
||||
}
|
||||
D3DDEVTYPE devType = D3DDEVTYPE_HAL;
|
||||
//D3DDEVTYPE devType = D3DDEVTYPE_REF;
|
||||
DWORD qLevels;
|
||||
DWORD qLevelsDepth;
|
||||
D3DMULTISAMPLE_TYPE type;
|
||||
for (type = D3DMULTISAMPLE_16_SAMPLES;
|
||||
type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
|
||||
hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
|
||||
devType, D3DFMT_D24S8, TRUE,
|
||||
type, &qLevels);
|
||||
qLevels = (hr == D3D_OK) ? qLevels : 0;
|
||||
hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT,
|
||||
devType, D3DFMT_A8R8G8B8, TRUE,
|
||||
type, &qLevelsDepth);
|
||||
qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
|
||||
qLevels = min(qLevels,qLevelsDepth);
|
||||
if (qLevels > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
qLevels = 0;
|
||||
IDirect3DDevice9* d3d9Device;
|
||||
D3DPRESENT_PARAMETERS pres;
|
||||
memset(&pres, 0, sizeof(pres));
|
||||
pres.EnableAutoDepthStencil = TRUE;
|
||||
pres.AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
pres.BackBufferCount = 2;
|
||||
pres.BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
pres.BackBufferHeight = 0;
|
||||
pres.BackBufferWidth = 0;
|
||||
if (qLevels > 0) {
|
||||
pres.MultiSampleType = type;
|
||||
pres.MultiSampleQuality = qLevels-1;
|
||||
} else {
|
||||
pres.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
pres.MultiSampleQuality = 0;
|
||||
}
|
||||
pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pres.Windowed = TRUE;
|
||||
pres.hDeviceWindow = hwnd;
|
||||
pres.PresentationInterval = 1;
|
||||
pres.Flags = 0;
|
||||
hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
|
||||
devType,
|
||||
hwnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING,
|
||||
&pres,
|
||||
&d3d9Device);
|
||||
D3DERR_INVALIDCALL;
|
||||
if (SUCCEEDED(hr)) {
|
||||
d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
|
||||
return d3d9Device;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This needs some improvement. D3D doesn't have the same notion of attach/detach
|
||||
// as GL. However, just allowing GDI to write to the window after creating the
|
||||
// D3D device seems to work.
|
||||
// We need to handle resizing. On XP and earlier Reset() will trash all our textures
|
||||
// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
|
||||
// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
|
||||
// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
|
||||
// when resized.
|
||||
|
||||
bool SkOSWindow::attachD3D9() {
|
||||
if (NULL == fD3D9Device) {
|
||||
fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
|
||||
}
|
||||
if (NULL != fD3D9Device) {
|
||||
((IDirect3DDevice9*)fD3D9Device)->BeginScene();
|
||||
fD3D9Attached = true;
|
||||
}
|
||||
return fD3D9Attached;
|
||||
}
|
||||
|
||||
void SkOSWindow::detachD3D9() {
|
||||
if (NULL != fD3D9Device) {
|
||||
((IDirect3DDevice9*)fD3D9Device)->EndScene();
|
||||
}
|
||||
fD3D9Attached = false;
|
||||
}
|
||||
|
||||
void SkOSWindow::presentD3D9() {
|
||||
if (NULL != fD3D9Device) {
|
||||
HRESULT hr;
|
||||
hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
|
||||
SkASSERT(SUCCEEDED(hr));
|
||||
hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
|
||||
SkASSERT(SUCCEEDED(hr));
|
||||
hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET |
|
||||
D3DCLEAR_STENCIL, 0x0, 0,
|
||||
0);
|
||||
SkASSERT(SUCCEEDED(hr));
|
||||
hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
|
||||
SkASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,184 @@
|
|||
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkWGL.h"
|
||||
|
||||
bool SkWGLExtensions::hasExtension(HDC dc, const char* ext) const {
|
||||
if (NULL == this->fGetExtensionsString) {
|
||||
return false;
|
||||
}
|
||||
if (!strcmp("WGL_ARB_extensions_string", ext)) {
|
||||
return true;
|
||||
}
|
||||
const char* extensionString = this->getExtensionsString(dc);
|
||||
int extLength = strlen(ext);
|
||||
|
||||
while (true) {
|
||||
int n = strcspn(extensionString, " ");
|
||||
if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
|
||||
return true;
|
||||
}
|
||||
if (0 == extensionString[n]) {
|
||||
return false;
|
||||
}
|
||||
extensionString += n+1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* SkWGLExtensions::getExtensionsString(HDC hdc) const {
|
||||
return fGetExtensionsString(hdc);
|
||||
}
|
||||
|
||||
BOOL SkWGLExtensions::choosePixelFormat(HDC hdc,
|
||||
const int* piAttribIList,
|
||||
const FLOAT* pfAttribFList,
|
||||
UINT nMaxFormats,
|
||||
int* piFormats,
|
||||
UINT* nNumFormats) const {
|
||||
return fChoosePixelFormat(hdc, piAttribIList, pfAttribFList,
|
||||
nMaxFormats, piFormats, nNumFormats);
|
||||
}
|
||||
|
||||
BOOL SkWGLExtensions::getPixelFormatAttribiv(HDC hdc,
|
||||
int iPixelFormat,
|
||||
int iLayerPlane,
|
||||
UINT nAttributes,
|
||||
const int *piAttributes,
|
||||
int *piValues) const {
|
||||
return fGetPixelFormatAttribiv(hdc, iPixelFormat, iLayerPlane,
|
||||
nAttributes, piAttributes, piValues);
|
||||
}
|
||||
|
||||
BOOL SkWGLExtensions::getPixelFormatAttribfv(HDC hdc,
|
||||
int iPixelFormat,
|
||||
int iLayerPlane,
|
||||
UINT nAttributes,
|
||||
const int *piAttributes,
|
||||
float *pfValues) const {
|
||||
return fGetPixelFormatAttribfv(hdc, iPixelFormat, iLayerPlane,
|
||||
nAttributes, piAttributes, pfValues);
|
||||
}
|
||||
HGLRC SkWGLExtensions::createContextAttribs(HDC hDC,
|
||||
HGLRC hShareContext,
|
||||
const int *attribList) const {
|
||||
return fCreateContextAttribs(hDC, hShareContext, attribList);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
#if defined(UNICODE)
|
||||
#define STR_LIT(X) L## #X
|
||||
#else
|
||||
#define STR_LIT(X) #X
|
||||
#endif
|
||||
|
||||
#define DUMMY_CLASS STR_LIT("DummyClass")
|
||||
|
||||
HWND create_dummy_window() {
|
||||
HMODULE module = GetModuleHandle(NULL);
|
||||
HWND dummy;
|
||||
RECT windowRect;
|
||||
windowRect.left = 0;
|
||||
windowRect.right = 8;
|
||||
windowRect.top = 0;
|
||||
windowRect.bottom = 8;
|
||||
|
||||
WNDCLASS wc;
|
||||
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC) DefWindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = module;
|
||||
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = NULL;
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = DUMMY_CLASS;
|
||||
|
||||
if(!RegisterClass(&wc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD style, exStyle;
|
||||
exStyle = WS_EX_CLIENTEDGE;
|
||||
style = WS_SYSMENU;
|
||||
|
||||
AdjustWindowRectEx(&windowRect, style, false, exStyle);
|
||||
if(!(dummy = CreateWindowEx(exStyle,
|
||||
DUMMY_CLASS,
|
||||
STR_LIT("DummyWindow"),
|
||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
|
||||
0, 0,
|
||||
windowRect.right-windowRect.left,
|
||||
windowRect.bottom-windowRect.top,
|
||||
NULL, NULL,
|
||||
module,
|
||||
NULL))) {
|
||||
UnregisterClass(DUMMY_CLASS, module);
|
||||
return NULL;
|
||||
}
|
||||
ShowWindow(dummy, SW_HIDE);
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
void destroy_dummy_window(HWND dummy) {
|
||||
DestroyWindow(dummy);
|
||||
HMODULE module = GetModuleHandle(NULL);
|
||||
UnregisterClass(DUMMY_CLASS, module);
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_PROC(NAME, SUFFIX) f##NAME = \
|
||||
(##NAME##Proc) wglGetProcAddress("wgl" #NAME #SUFFIX)
|
||||
|
||||
SkWGLExtensions::SkWGLExtensions()
|
||||
: fGetExtensionsString(NULL)
|
||||
, fChoosePixelFormat(NULL)
|
||||
, fGetPixelFormatAttribfv(NULL)
|
||||
, fGetPixelFormatAttribiv(NULL)
|
||||
, fCreateContextAttribs(NULL) {
|
||||
HDC prevDC = wglGetCurrentDC();
|
||||
HGLRC prevGLRC = wglGetCurrentContext();
|
||||
|
||||
PIXELFORMATDESCRIPTOR dummyPFD;
|
||||
|
||||
ZeroMemory(&dummyPFD, sizeof(dummyPFD));
|
||||
dummyPFD.nSize = sizeof(dummyPFD);
|
||||
dummyPFD.nVersion = 1;
|
||||
dummyPFD.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
dummyPFD.iPixelType = PFD_TYPE_RGBA;
|
||||
dummyPFD.cColorBits = 32;
|
||||
dummyPFD.cDepthBits = 0;
|
||||
dummyPFD.cStencilBits = 8;
|
||||
dummyPFD.iLayerType = PFD_MAIN_PLANE;
|
||||
HWND dummyWND = create_dummy_window();
|
||||
if (dummyWND) {
|
||||
HDC dummyDC = GetDC(dummyWND);
|
||||
int dummyFormat = ChoosePixelFormat(dummyDC, &dummyPFD);
|
||||
SetPixelFormat(dummyDC, dummyFormat, &dummyPFD);
|
||||
HGLRC dummyGLRC = wglCreateContext(dummyDC);
|
||||
SkASSERT(dummyGLRC);
|
||||
wglMakeCurrent(dummyDC, dummyGLRC);
|
||||
|
||||
GET_PROC(GetExtensionsString, ARB);
|
||||
GET_PROC(ChoosePixelFormat, ARB);
|
||||
GET_PROC(GetPixelFormatAttribiv, ARB);
|
||||
GET_PROC(GetPixelFormatAttribfv, ARB);
|
||||
GET_PROC(CreateContextAttribs, ARB);
|
||||
|
||||
wglMakeCurrent(dummyDC, NULL);
|
||||
wglDeleteContext(dummyGLRC);
|
||||
destroy_dummy_window(dummyWND);
|
||||
}
|
||||
|
||||
wglMakeCurrent(prevDC, prevGLRC);
|
||||
}
|
Загрузка…
Ссылка в новой задаче