aboutsummaryrefslogtreecommitdiff
path: root/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp')
-rw-r--r--src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp507
1 files changed, 507 insertions, 0 deletions
diff --git a/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp b/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp
new file mode 100644
index 000000000..03b016ab7
--- /dev/null
+++ b/src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp
@@ -0,0 +1,507 @@
+/*
+ * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code 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 General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "sun_java2d_d3d_D3DGraphicsDevice.h"
+#include "D3DGraphicsDevice.h"
+#include "D3DPipelineManager.h"
+#include "D3DRenderQueue.h"
+#include "Trace.h"
+#include "awt_Toolkit.h"
+#include "awt_Window.h"
+
+extern jobject CreateDisplayMode(JNIEnv* env, jint width, jint height,
+ jint bitDepth, jint refreshRate);
+extern void addDisplayMode(JNIEnv* env, jobject arrayList, jint width,
+ jint height, jint bitDepth, jint refreshRate);
+
+void InitD3D(void *pReturn)
+{
+ J2dTraceLn(J2D_TRACE_INFO, "InitD3D");
+
+ jboolean *pRet = (jboolean *)pReturn;
+
+ D3DPipelineManager *pMgr = D3DPipelineManager::CreateInstance();
+ if (pMgr == NULL) {
+ J2dTraceLn(J2D_TRACE_ERROR, "InitD3D: could not create or init d3d");
+ *pRet = JNI_FALSE;
+ } else {
+ J2dTraceLn(J2D_TRACE_INFO, "InitD3D: successfully initialized d3d");
+ *pRet = JNI_TRUE;
+ }
+}
+
+extern "C" {
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: initD3D
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_initD3D
+ (JNIEnv *env, jclass)
+{
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_initD3D");
+
+ jboolean result = JNI_FALSE;
+ AwtToolkit::GetInstance().InvokeFunction(InitD3D, &result);
+ J2dTraceLn1(J2D_TRACE_INFO, "D3DGD_initD3D: result=%x", result);
+ return result;
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: getDeviceIdNative
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceIdNative
+ (JNIEnv *env, jclass d3dsdc, jint gdiScreen)
+{
+ D3DPipelineManager *pMgr;
+ UINT adapter;
+ D3DADAPTER_IDENTIFIER9 aid;
+ IDirect3D9 *pd3d9;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getDeviceIdNative");
+
+ pMgr = D3DPipelineManager::GetInstance();
+ RETURN_STATUS_IF_NULL(pMgr, NULL);
+ pd3d9 = pMgr->GetD3DObject();
+ RETURN_STATUS_IF_NULL(pd3d9, NULL);
+
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+ if (FAILED(pd3d9->GetAdapterIdentifier(adapter, 0, &aid))) {
+ return NULL;
+ }
+
+ // ('%d.' will take no more than 6+1 chars since we are printing a WORD)
+ // AAAA&BBBB MAX_DEVICE_IDENTIFIER_STRING (%d.%d.%d.%d)0
+ size_t len = (4+1+4 +1+MAX_DEVICE_IDENTIFIER_STRING+1 +1+(6+1)*4+1 +1);
+ WCHAR *pAdapterId = new WCHAR[len];
+ RETURN_STATUS_IF_NULL(pAdapterId, NULL);
+
+ _snwprintf(pAdapterId, len, L"%x&%x %S (%d.%d.%d.%d)",
+ 0xffff & aid.VendorId, 0xffff & aid.DeviceId, aid.Description,
+ HIWORD(aid.DriverVersion.HighPart),
+ LOWORD(aid.DriverVersion.HighPart),
+ HIWORD(aid.DriverVersion.LowPart),
+ LOWORD(aid.DriverVersion.LowPart));
+ // _snwprintf doesn't add 0 at the end if the formatted string didn't fit
+ // in the buffer so we have to make sure it is null terminated
+ pAdapterId[len-1] = (WCHAR)0;
+
+ J2dTraceLn1(J2D_TRACE_VERBOSE, " id=%S", pAdapterId);
+
+ jstring ret = JNU_NewStringPlatform(env, pAdapterId);
+
+ delete pAdapterId;
+
+ return ret;
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: getDeviceCapsNative
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceCapsNative
+ (JNIEnv *env, jclass d3dsdc, jint gdiScreen)
+{
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ UINT adapter;
+
+ J2dRlsTraceLn(J2D_TRACE_INFO, "D3DGD_getDeviceCapsNative");
+
+ pMgr = D3DPipelineManager::GetInstance();
+ RETURN_STATUS_IF_NULL(pMgr, CAPS_EMPTY);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(pMgr->GetD3DContext(adapter, &pCtx))) {
+ J2dRlsTraceLn1(J2D_TRACE_ERROR,
+ "D3DGD_getDeviceCapsNative: device %d disabled", adapter);
+ return CAPS_EMPTY;
+ }
+ return pCtx->GetContextCaps();
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: enterFullScreenExclusiveNative
+ * Signature: (IJ)V
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_enterFullScreenExclusiveNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen, jlong window)
+{
+ HRESULT res;
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ HWND hWnd;
+ AwtWindow *w;
+ D3DPRESENT_PARAMETERS newParams, *pCurParams;
+ D3DDISPLAYMODE dm;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_enterFullScreenExclusiveNative");
+
+ RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) {
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return JNI_FALSE;
+ }
+
+ w = (AwtWindow *)AwtComponent::GetComponent((HWND)window);
+ if (w == NULL || !::IsWindow(hWnd = w->GetTopLevelHWnd())) {
+ J2dTraceLn(J2D_TRACE_WARNING,
+ "D3DGD_enterFullScreenExclusiveNative: disposed window");
+ return JNI_FALSE;
+ }
+
+ // REMIND: should we also move the non-topleve window from
+ // being on top here (it's moved to front in GraphicsDevice.setFSW())?
+
+ pCtx->Get3DObject()->GetAdapterDisplayMode(adapter, &dm);
+ pCurParams = pCtx->GetPresentationParams();
+
+ // let the mananger know that we're entering the fs mode, it will
+ // set the proper current focus window for us, which ConfigureContext will
+ // use when creating the device
+ pMgr->SetFSFocusWindow(adapter, hWnd);
+
+ newParams = *pCurParams;
+ newParams.hDeviceWindow = hWnd;
+ newParams.Windowed = FALSE;
+ newParams.BackBufferCount = 1;
+ newParams.BackBufferFormat = dm.Format;
+ newParams.FullScreen_RefreshRateInHz = dm.RefreshRate;
+ newParams.BackBufferWidth = dm.Width;
+ newParams.BackBufferHeight = dm.Height;
+ newParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ newParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ res = pCtx->ConfigureContext(&newParams);
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return SUCCEEDED(res);
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: exitFullScreenExclusiveNative
+ * Signature: (I)V
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_exitFullScreenExclusiveNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen)
+{
+ HRESULT res;
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ D3DPRESENT_PARAMETERS newParams, *pCurParams;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_exitFullScreenExclusiveNative");
+
+ RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) {
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return JNI_FALSE;
+ }
+
+ pCurParams = pCtx->GetPresentationParams();
+
+ newParams = *pCurParams;
+ // we're exiting fs, the device window can be 0
+ newParams.hDeviceWindow = 0;
+ newParams.Windowed = TRUE;
+ newParams.BackBufferFormat = D3DFMT_UNKNOWN;
+ newParams.BackBufferCount = 1;
+ newParams.FullScreen_RefreshRateInHz = 0;
+ newParams.BackBufferWidth = 0;
+ newParams.BackBufferHeight = 0;
+ newParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
+ newParams.SwapEffect = D3DSWAPEFFECT_COPY;
+
+ res = pCtx->ConfigureContext(&newParams);
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+
+ // exited fs, update current focus window
+ // note that we call this after this adapter exited fs mode so that
+ // the rest of the adapters can be reset
+ pMgr->SetFSFocusWindow(adapter, 0);
+
+ return SUCCEEDED(res);
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: configDisplayModeNative
+ * Signature: (IJIIII)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_configDisplayModeNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen, jlong window,
+ jint width, jint height, jint bitDepth, jint refreshRate)
+{
+ HRESULT res;
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ D3DPRESENT_PARAMETERS newParams, *pCurParams;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_configDisplayModeNative");
+
+ RETURN_IF_NULL(pMgr = D3DPipelineManager::GetInstance());
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) {
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return;
+ }
+
+ pCurParams = pCtx->GetPresentationParams();
+
+ newParams = *pCurParams;
+ newParams.BackBufferWidth = width;
+ newParams.BackBufferHeight = height;
+ newParams.FullScreen_RefreshRateInHz = refreshRate;
+ newParams.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ // we leave the swap effect so that it's more likely
+ // to be the one user selected initially
+// newParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
+
+ if (bitDepth == 32) {
+ newParams.BackBufferFormat = D3DFMT_X8R8G8B8;
+ } else if (bitDepth == 16) {
+ UINT modeNum;
+ D3DDISPLAYMODE mode;
+ IDirect3D9 *pd3d9;
+ UINT modesCount;
+
+ RETURN_IF_NULL(pd3d9 = pMgr->GetD3DObject());
+
+ modesCount = pd3d9->GetAdapterModeCount(adapter, D3DFMT_R5G6B5);
+ if (modesCount == 0) {
+ modesCount = pd3d9->GetAdapterModeCount(adapter, D3DFMT_X1R5G5B5);
+ }
+
+ newParams.BackBufferFormat = D3DFMT_UNKNOWN;
+ for (modeNum = 0; modeNum < modesCount; modeNum++) {
+ if (SUCCEEDED(pd3d9->EnumAdapterModes(adapter, D3DFMT_R5G6B5,
+ modeNum, &mode)))
+ {
+ if (mode.Width == width && mode.Height == height &&
+ mode.RefreshRate == refreshRate)
+ {
+ // prefer 565 over 555
+ if (mode.Format == D3DFMT_R5G6B5) {
+ newParams.BackBufferFormat = D3DFMT_R5G6B5;
+ break;
+ } else if (mode.Format == D3DFMT_X1R5G5B5) {
+ newParams.BackBufferFormat = D3DFMT_X1R5G5B5;
+ }
+ }
+ }
+ }
+ if (newParams.BackBufferFormat == D3DFMT_UNKNOWN) {
+ J2dRlsTraceLn(J2D_TRACE_ERROR,
+ "D3DGD_configDisplayModeNative: no 16-bit formats");
+ return;
+ }
+ } else {
+ J2dRlsTraceLn1(J2D_TRACE_ERROR,
+ "D3DGD_configDisplayModeNative: unsupported depth: %d",
+ bitDepth);
+ return;
+ }
+
+ J2dTraceLn4(J2D_TRACE_VERBOSE, " changing to dm: %dx%dx%d@%d",
+ newParams.BackBufferWidth, newParams.BackBufferHeight,
+ bitDepth, refreshRate);
+ J2dTraceLn1(J2D_TRACE_VERBOSE, " selected backbuffer format: %d",
+ newParams.BackBufferFormat);
+
+ res = pCtx->ConfigureContext(&newParams);
+ if (SUCCEEDED(res)) {
+ // the full screen window doesn't receive WM_SIZE event when
+ // the display mode changes (it does get resized though) so we need to
+ // generate the event ourselves
+ ::SendMessage(newParams.hDeviceWindow, WM_SIZE, width, height);
+ }
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+}
+
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: getCurrentDisplayModeNative
+ * Signature: (I)Ljava/awt/DisplayMode;
+ */
+JNIEXPORT jobject JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_getCurrentDisplayModeNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen)
+{
+ D3DPipelineManager *pMgr;
+ IDirect3D9 *pd3d9;
+ jobject ret = NULL;
+ D3DDISPLAYMODE mode;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getCurrentDisplayModeNative");
+
+ RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), NULL);
+ RETURN_STATUS_IF_NULL(pd3d9 = pMgr->GetD3DObject(), NULL);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (SUCCEEDED(pd3d9->GetAdapterDisplayMode(adapter, &mode))) {
+ int bitDepth = -1;
+ // these are the only three valid screen formats
+ switch (mode.Format) {
+ case D3DFMT_X8R8G8B8: bitDepth = 32; break;
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5: bitDepth = 16; break;
+ }
+ J2dTraceLn4(J2D_TRACE_VERBOSE,
+ " current dm: %dx%dx%d@%d",
+ mode.Width, mode.Height, bitDepth, mode.RefreshRate);
+ ret = CreateDisplayMode(env, mode.Width, mode.Height, bitDepth,
+ mode.RefreshRate);
+ }
+ return ret;
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: enumDisplayModesNative
+ * Signature: (ILjava/util/ArrayList;)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_enumDisplayModesNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen, jobject arrayList)
+{
+ D3DPipelineManager *pMgr;
+ IDirect3D9 *pd3d9;
+ jobject ret = NULL;
+ D3DDISPLAYMODE mode;
+ UINT formatNum, modeNum, modesCount;
+ UINT adapter;
+ // EnumAdapterModes treats 555 and 565 formats as equivalents
+ static D3DFORMAT formats[] =
+ { D3DFMT_X8R8G8B8, D3DFMT_R5G6B5 };
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_enumDisplayModesNative");
+
+ RETURN_IF_NULL(pMgr = D3DPipelineManager::GetInstance());
+ RETURN_IF_NULL(pd3d9 = pMgr->GetD3DObject());
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ for (formatNum = 0; formatNum < 3; formatNum++) {
+ modesCount = pd3d9->GetAdapterModeCount(adapter, formats[formatNum]);
+ for (modeNum = 0; modeNum < modesCount; modeNum++) {
+ if (SUCCEEDED(pd3d9->EnumAdapterModes(adapter, formats[formatNum],
+ modeNum, &mode)))
+ {
+ int bitDepth = -1;
+ // these are the only three valid screen formats,
+ // 30-bit is returned as X8R8G8B8
+ switch (mode.Format) {
+ case D3DFMT_X8R8G8B8: bitDepth = 32; break;
+ case D3DFMT_R5G6B5:
+ case D3DFMT_X1R5G5B5: bitDepth = 16; break;
+ }
+ J2dTraceLn4(J2D_TRACE_VERBOSE, " found dm: %dx%dx%d@%d",
+ mode.Width, mode.Height, bitDepth,mode.RefreshRate);
+ addDisplayMode(env, arrayList, mode.Width, mode.Height,
+ bitDepth, mode.RefreshRate);
+ }
+ }
+ }
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: getAvailableAcceleratedMemoryNative
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_getAvailableAcceleratedMemoryNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen)
+{
+ // REMIND: looks like Direct3D provides information about texture memory
+ // only via IDirect3DDevice9::GetAvailableTextureMem, however, it
+ // seems to report the same amount as direct draw used to.
+ HRESULT res;
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ IDirect3DDevice9 *pd3dDevice;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_getAvailableAcceleratedMemoryNative");
+
+ RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), 0L);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) {
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return 0L;
+ }
+ RETURN_STATUS_IF_NULL(pd3dDevice = pCtx->Get3DDevice(), 0L);
+
+ UINT mem = pd3dDevice->GetAvailableTextureMem();
+ J2dTraceLn1(J2D_TRACE_VERBOSE, " available memory=%d", mem);
+ return mem;
+}
+
+/*
+ * Class: sun_java2d_d3d_D3DGraphicsDevice
+ * Method: isD3DAvailableOnDeviceNative
+ * Signature: (I)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_d3d_D3DGraphicsDevice_isD3DAvailableOnDeviceNative
+ (JNIEnv *env, jclass gdc, jint gdiScreen)
+{
+ HRESULT res;
+ D3DPipelineManager *pMgr;
+ D3DContext *pCtx;
+ UINT adapter;
+
+ J2dTraceLn(J2D_TRACE_INFO, "D3DGD_isD3DAvailableOnDeviceNative");
+
+ RETURN_STATUS_IF_NULL(pMgr = D3DPipelineManager::GetInstance(), JNI_FALSE);
+ adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen);
+
+ if (FAILED(res = pMgr->GetD3DContext(adapter, &pCtx))) {
+ D3DRQ_MarkLostIfNeeded(res, D3DRQ_GetCurrentDestination());
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+} // extern "C"