diff options
Diffstat (limited to 'src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp')
-rw-r--r-- | src/windows/native/sun/java2d/d3d/D3DGraphicsDevice.cpp | 507 |
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" |