/* * Copyright 2005-2006 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 "D3DSurfaceData.h" #include "D3DContext.h" #include "jlong.h" #include "jni_util.h" #include "Trace.h" #include "ddrawUtils.h" #include "Devices.h" #include "Win32SurfaceData.h" #include "sun_java2d_d3d_D3DBackBufferSurfaceData.h" extern LockFunc Win32OSSD_Lock; extern GetRasInfoFunc Win32OSSD_GetRasInfo; extern UnlockFunc Win32OSSD_Unlock; extern DisposeFunc Win32OSSD_Dispose; extern GetDCFunc Win32OSSD_GetDC; extern ReleaseDCFunc Win32OSSD_ReleaseDC; extern InvalidateSDFunc Win32OSSD_InvalidateSD; extern RestoreSurfaceFunc Win32OSSD_RestoreSurface; extern DisposeFunc Win32BBSD_Dispose; extern "C" { RestoreSurfaceFunc D3DSD_RestoreSurface; /* * D3D-surface specific restore function. * We need to make sure the D3DContext is notified if the * surface is lost (only if this surface is the current target, * otherwise it's possible that it'll get restored (along with its * depth buffer), and the context will still think that the clipping * that's set for this surface is valid. * Consider this scenario: * do { * vi.validate(gc); // validated, vi's surface is restored, clipping is lost * // render stuff using d3d, clipping is reset * // -> surface loss event happens * // do a DD blit of the VI to the screen * // at this point the VI surface will be marked lost * // and will be restored in validate() next time around, * // losing the clipping w/o notifying the D3D context * } while (vi.surfaceLost()); */ void D3DSD_RestoreSurface(JNIEnv *env, Win32SDOps *wsdo) { J2dTraceLn(J2D_TRACE_INFO, "D3DSD_RestoreSurface"); D3DSDOps *d3dsdo = (D3DSDOps *)wsdo; // This is needed only for non-textures, since textures can't // lose their surfaces, as they're managed. if (!(d3dsdo->d3dType & D3D_TEXTURE_SURFACE) && wsdo->lpSurface != NULL) { if (wsdo->ddInstance != NULL && wsdo->ddInstance->ddObject != NULL) { D3DContext *d3dContext = wsdo->ddInstance->ddObject->GetD3dContext(); if (d3dContext != NULL) { d3dContext->InvalidateIfTarget(env, wsdo->lpSurface); } } } Win32OSSD_RestoreSurface(env, wsdo); } /* * Class: sun_java2d_d3d_D3DSurfaceData * Method: initOps * Signature: (Ljava/lang/Object;)V */ JNIEXPORT void JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initOps(JNIEnv *env, jobject wsd, jint depth, jint transparency) { J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_initOps"); Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_InitOps(env, wsd, sizeof(D3DSDOps)); wsdo->sdOps.Lock = Win32OSSD_Lock; wsdo->sdOps.GetRasInfo = Win32OSSD_GetRasInfo; wsdo->sdOps.Unlock = Win32OSSD_Unlock; wsdo->sdOps.Dispose = Win32OSSD_Dispose; wsdo->RestoreSurface = D3DSD_RestoreSurface; wsdo->GetDC = Win32OSSD_GetDC; wsdo->ReleaseDC = Win32OSSD_ReleaseDC; wsdo->InvalidateSD = Win32OSSD_InvalidateSD; wsdo->invalid = JNI_FALSE; wsdo->lockType = WIN32SD_LOCK_UNLOCKED; wsdo->window = NULL; wsdo->backBufferCount = 0; wsdo->depth = depth; switch (depth) { case 8: wsdo->pixelStride = 1; break; case 15: //555 wsdo->pixelStride = 2; wsdo->pixelMasks[0] = 0x1f << 10; wsdo->pixelMasks[1] = 0x1f << 5; wsdo->pixelMasks[2] = 0x1f; break; case 16: //565 wsdo->pixelStride = 2; wsdo->pixelMasks[0] = 0x1f << 11; wsdo->pixelMasks[1] = 0x3f << 5; wsdo->pixelMasks[2] = 0x1f; break; case 24: wsdo->pixelStride = 3; break; case 32: //x888 wsdo->pixelStride = 4; wsdo->pixelMasks[0] = 0xff0000; wsdo->pixelMasks[1] = 0x00ff00; wsdo->pixelMasks[2] = 0x0000ff; break; } wsdo->surfaceLock = new CriticalSection(); wsdo->surfaceLost = FALSE; wsdo->transparency = transparency; wsdo->surfacePuntData.usingDDSystem = FALSE; wsdo->surfacePuntData.lpSurfaceSystem = NULL; wsdo->surfacePuntData.lpSurfaceVram = NULL; wsdo->surfacePuntData.numBltsSinceRead = 0; wsdo->surfacePuntData.pixelsReadSinceBlt = 0; wsdo->surfacePuntData.numBltsThreshold = 2; wsdo->gdiOpPending = FALSE; } jboolean init_D3DSDO(JNIEnv* env, Win32SDOps* wsdo, jint width, jint height, jint d3dSurfaceType, jint screen) { // default in case of an error wsdo->lpSurface = NULL; wsdo->ddInstance = NULL; { Devices::InstanceAccess devices; wsdo->device = devices->GetDeviceReference(screen, FALSE); } if (wsdo->device == NULL) { J2dTraceLn1(J2D_TRACE_WARNING, "init_D3DSDO: Incorrect "\ "screen number (screen=%d)", screen); wsdo->invalid = TRUE; return JNI_FALSE; } wsdo->w = width; wsdo->h = height; wsdo->surfacePuntData.disablePunts = TRUE; return JNI_TRUE; } /* * Class: sun_java2d_d3d_D3DSurfaceData * Method: initOffScreenSurface * Signature: (JJJIIII)I */ JNIEXPORT jint JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initOffScreenSurface (JNIEnv *env, jobject sData, jlong pCtx, jlong pData, jlong parentPdata, jint width, jint height, jint d3dSurfaceType, jint screen) { Win32SDOps *wsdo = (Win32SDOps *)jlong_to_ptr(pData); D3DContext *pd3dc = (D3DContext *)jlong_to_ptr(pCtx); J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_initOffScreenSurface"); J2dTraceLn4(J2D_TRACE_VERBOSE, " width=%-4d height=%-4d type=%-3d scr=%-3d", width, height, d3dSurfaceType, screen); // REMIND: ideally this should be done in initOps if (d3dSurfaceType == D3D_ATTACHED_SURFACE) { wsdo->sdOps.Dispose = Win32BBSD_Dispose; } if (init_D3DSDO(env, wsdo, width, height, d3dSurfaceType, screen) == JNI_FALSE) { SurfaceData_ThrowInvalidPipeException(env, "Can't create offscreen surface"); return PF_INVALID; } HMONITOR hMon = (HMONITOR)wsdo->device->GetMonitor(); DDrawObjectStruct *ddInstance = GetDDInstanceForDevice(hMon); if (!ddInstance || !ddInstance->valid || !pd3dc) { return PF_INVALID; } if (d3dSurfaceType == D3D_ATTACHED_SURFACE) { // REMIND: still using the old path. ideally the creation of attached // surface shoudld be done in the same way as other types of surfaces, // that is, in D3DContext::CreateSurface, but we really don't use // anything from D3DContext to get an attached surface, so this // was left here. Win32SDOps *wsdo_parent = (Win32SDOps *)jlong_to_ptr(parentPdata); // we're being explicit here: requesting backbuffer, and render target DDrawSurface* pNew = wsdo_parent->lpSurface == NULL ? NULL : wsdo_parent->lpSurface-> GetDDAttachedSurface(DDSCAPS_BACKBUFFER|DDSCAPS_3DDEVICE); if (pNew == NULL || FAILED(pd3dc->AttachDepthBuffer(pNew->GetDXSurface()))) { J2dRlsTraceLn1(J2D_TRACE_ERROR, "D3DSD_initSurface: GetAttachedSurface for parent"\ " wsdo_parent->lpSurface=0x%x failed", wsdo_parent->lpSurface); if (pNew != NULL) { delete pNew; } SurfaceData_ThrowInvalidPipeException(env, "Can't create attached offscreen surface"); return PF_INVALID; } wsdo->lpSurface = pNew; wsdo->ddInstance = ddInstance; J2dTraceLn2(J2D_TRACE_VERBOSE, "D3DSD_initSurface: created attached surface: "\ "wsdo->lpSurface=0x%x for parent "\ "wsdo_parent->lpSurface=0x%x", wsdo->lpSurface, wsdo_parent->lpSurface); // we don't care about pixel format for non-texture surfaces return PF_INVALID; } DXSurface *dxSurface = NULL; jint pf = PF_INVALID; HRESULT res; if (SUCCEEDED(res = pd3dc->CreateSurface(env, wsdo->w, wsdo->h, wsdo->depth, wsdo->transparency, d3dSurfaceType, &dxSurface, &pf))) { // REMIND: put all the error-handling stuff here from // DDCreateOffScreenSurface wsdo->lpSurface = new DDrawSurface(ddInstance->ddObject, dxSurface); wsdo->surfacePuntData.lpSurfaceVram = wsdo->lpSurface; wsdo->ddInstance = ddInstance; // the dimensions of the surface may be adjusted in case of // textures wsdo->w = dxSurface->GetWidth(); wsdo->h = dxSurface->GetHeight(); J2dTraceLn1(J2D_TRACE_VERBOSE, "D3DSurfaceData_initSurface: created surface: "\ "wsdo->lpSurface=0x%x", wsdo->lpSurface); } else { DebugPrintDirectDrawError(res, "D3DSurfaceData_initSurface: "\ "CreateSurface failed"); // REMIND: should use some other way to signal that // surface creation was unsuccessful SurfaceData_ThrowInvalidPipeException(env, "Can't create offscreen surf"); } return pf; } /* * Class: sun_java2d_d3d_D3DBackBufferSurfaceData * Method: restoreDepthBuffer * Signature: ()V */ JNIEXPORT void JNICALL Java_sun_java2d_d3d_D3DBackBufferSurfaceData_restoreDepthBuffer(JNIEnv *env, jobject sData) { Win32SDOps *wsdo = Win32SurfaceData_GetOpsNoSetup(env, sData); J2dTraceLn1(J2D_TRACE_INFO, "D3DBBSD_restoreDepthBuffer: wsdo=0x%x", wsdo); if (wsdo != NULL) { if (!DDRestoreSurface(wsdo)) { // Failure - throw exception J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DBBSD_restoreDepthBuffer: failed to "\ "restore depth buffer"); SurfaceData_ThrowInvalidPipeException(env, "RestoreDepthBuffer failure"); } } } }