/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "sun_java2d_windows_GDIWindowSurfaceData.h"
#include "GDIWindowSurfaceData.h"
#include "GraphicsPrimitiveMgr.h"
#include "Region.h"
#include "Disposer.h"
#include "WindowsFlags.h"
#include "awt_Component.h"
#include "awt_Palette.h"
#include "awt_Win32GraphicsDevice.h"
#include "gdefs.h"
#include "Trace.h"
#include "Devices.h"
#include "jni_util.h"
extern CriticalSection windowMoveLock;
extern "C"
{
// REMIND: handle error when creation fails
info = new ThreadGraphicsInfo;
" current batch limit for for thread 0x%x is %d",
GetCurrentThreadId(), ::GdiGetBatchLimit());
// Fix for bug 4374079
::GdiSetBatchLimit(1);
ptr_to_jlong(info));
}
// the hDC is NULL for offscreen surfaces - we don't store it
// in TLS as it must be created new every time.
{
// Init graphics state, either because this is our first time
// using it in this thread or because this thread is now
// dealing with a different window than it was last time.
//check extra condition:
//(info->wsdoTimeStamp != wsdo->timeStamp).
//Checking memory addresses (info->wsdo != wsdo) will not detect
//that wsdo points to a newly allocated structure in case
//that structure just got allocated at a "recycled" memory location
//which previously was pointed by info->wsdo
//see bug# 6859086
// Release cached DC. We use deferred DC releasing mechanism because
// the DC is associated with cached wsdo and component peer,
// which may've been disposed by this time, and we have
// no means of checking against it.
}
// This is a window surface
// First, init the HDC object
return;
}
// Note that on NT4 we don't need to do a realize here: the
// palette-sharing takes care of color issues for us. But
// on win98 if we don't realize a DC's palette, that
// palette does not appear to have correct access to the
// logical->system mapping.
// Second, init the rest of the graphics state
// Make window-relative from client-relative
//Likewise, translate GDI calls from client-relative to window-relative
}
// Finally, set these new values in the info for this thread
}
// cached brush and pen are not associated with any DC, and can be
// were set to the new hdc
}
}
//store the address and time stamp of newly allocated GDIWinSDOps structure
}
}
/**
* Releases native data stored in Thread local storage.
* Called by the Disposer when the associated thread dies.
*/
// move the DC from the active dcs list to
// the passive dc list to be released later
}
}
}
}
}
delete info;
}
}
/**
* Returns current Thread object.
*/
} /* JNI_GetCurrentThread() */
/**
* Return the data associated with this thread.
* NOTE: This function assumes that the SetupThreadGraphicsInfo()
* function has already been called for this situation (thread,
* window, etc.), so we can assume that the thread info contains
* a valid hDC. This should usually be the case since GDIWinSD_Setup
* is called as part of the GetOps() process.
*/
GDIWinSDOps *wsdo) {
}
if (!info) {
}
}
} // extern "C"
/**
* This source file contains support code for loops using the
* SurfaceData interface to talk to a Win32 drawable from native
* code.
*/
{
int numScreens;
{
}
if( numScreens > 1 ) {
::OffsetRect(&rView,
}
}
}
return retCode;
}
extern "C" {
void
{
if (threadInfoIndex == TLS_OUT_OF_INDEXES) {
threadInfoIndex = TlsAlloc();
}
}
/**
* Utility function to make sure that native and java-level
* surface depths are matched. They can be mismatched when display-depths
* change, either between the creation of the Java surfaceData structure
* and the native ddraw surface, or later when a surface is automatically
* adjusted to be the new display depth (even if it was created in a different
* depth to begin with)
*/
{
if (nativeDepth != javaDepth) {
switch (nativeDepth) {
case 0: // Error condition: something is wrong with the surface
case 8:
case 24:
// Java and native surface depths should match exactly for
// these cases
return FALSE;
break;
case 16:
// Java surfaceData should be 15 or 16 bits
return FALSE;
}
break;
case 32:
// Could have this native depth for either 24- or 32-bit
// Java surfaceData
return FALSE;
}
break;
default:
// should not get here, but if we do something is odd, so
// just register a failure
return FALSE;
}
}
return TRUE;
}
/*
* Class: sun_java2d_windows_GDIWindowSurfaceData
* Method: initIDs
* Signature: ()V
*/
{
}
/*
* Class: sun_java2d_windows_GDIWindowSurfaceData
* Method: initOps
*/
{
return;
}
// Init the DIB pixelStride and pixel masks according to
// the pixel depth. In the 8-bit case, there are no
// masks as a palette DIB is used instead. Likewise
// in the 24-bit case, Windows doesn't expect the masks
switch (depth) {
case 8:
break;
case 15: //555
break;
case 16: //565
break;
case 24:
break;
case 32: //888
break;
}
// GDIWindowSurfaceData_GetWindow will throw NullPointerException
// if wsdo->window is NULL
{
}
{
"GDIWindowSurfaceData_initOps: Surface depth mismatch: "\
"wsdo->depth=%d device depth=%d. Surface invalidated.",
} else {
"GDIWindowSurfaceData_initOps: Incorrect "\
"screen number (screen=%d). Surface invalidated.",
screen);
}
}
}
{
// REMIND: There was originally a condition check here to make sure
// that we were really dealing with a GDIWindowSurfaceData object, but
// it did not allow for the existence of other win32-accelerated
// surface data objects (e.g., Win32OffScreenSurfaceData). I've
// removed the check for now, but we should replace it with another,
// more general check against Win32-related surfaces.
return (GDIWinSDOps *) ops;
}
{
// use the 'no setup' version of GetOps
return (GDIWinSDOps *) ops;
}
{
"GDIWindowSurfaceData_GetComp: Null pData? pData=0x%x",
pData);
if (beingShutdown == JNI_TRUE) {
return (AwtComponent *) NULL;
}
try {
} catch (awt_toolkit_shutdown&) {
return (AwtComponent *) NULL;
}
"GDIWindowSurfaceData: bounds changed");
} else {
}
return (AwtComponent *) NULL;
}
return static_cast<AwtComponent*>(pData);
}
{
"GDIWindowSurfaceData_GetWindow: null component");
}
"GDIWindowSurfaceData_GetWindow: disposed component");
}
}
return window;
}
} /* extern "C" */
{
return JNI_FALSE;
}
switch (nComplexity) {
case COMPLEXREGION:
{
" complex clipping region");
// check to see if the view itself has a complex clip.
// ::GetClipBox is only API which returns overlapped window status
// so we set the rView as our clip, and then see if resulting
// clip is complex.
// Only other way to figure this out would be to walk the
// overlapping windows (no API to get the actual visible clip
// list). Then we'd still have to merge that info with the
// clip region for the dc (if it exists).
// REMIND: we can cache the CreateRectRgnIndirect result,
// and only override with ::SetRectRgn
// First, create a region handle (need existing HRGN for
// the following call).
if (-1 == clipStatus) {
"GDIWinSD_SimpleClip: failed due to clip status");
::DeleteObject(rgnSave);
return JNI_FALSE;
}
::DeleteObject(rgnSave);
// Now, test the new clip box. If it's still not a
// SIMPLE region, then our bounds must intersect part of
// the clipping article
if (SIMPLEREGION != nComplexity) {
"GDIWinSD_SimpleClip: failed due to complexity");
return JNI_FALSE;
}
}
// NOTE: No break here - we want to fall through into the
// SIMPLE case, adjust our bounds by the new rClip rect
// and make sure that our locking bounds are not empty.
case SIMPLEREGION:
// Constrain the bounds to the given clip box
}
}
}
}
// If the bounds are 0 or negative, then the bounds have
// been obscured by the clip box, so return FALSE
// REMIND: We should probably do something different here
// instead of simply returning FALSE. Since the bounds are
// empty we won't end up drawing anything, so why spend the
// effort of returning false and having GDI do a LOCK_BY_DIB?
// Perhaps we need a new lock code that will indicate that we
// shouldn't bother drawing?
"GDIWinSD_SimpleClip: failed due to empty bounds");
return JNI_FALSE;
}
break;
case NULLREGION:
case ERROR:
default:
"GDIWinSD_SimpleClip: failed due to incorrect complexity=%d",
return JNI_FALSE;
}
return JNI_TRUE;
}
{
/* This surfaceLock replaces an earlier implementation which used a
monitor associated with the peer. That implementation was prone
to deadlock problems, so it was replaced by a lock that does not
have dependencies outside of this thread or object.
However, this lock doesn't necessarily do all that we want.
For example, a user may issue a call which results in a DIB lock
and another call which results in a DDraw Blt. We can't guarantee
what order these operations happen in (they are driver and
video-card dependent), so locking around the issue of either of
those calls won't necessarily guarantee a particular result.
The real solution might be to move away from mixing our
rendering API's. That is, if we only used DDraw, then we could
guarantee that all rendering operations would happen in a given
order. Similarly for GDI. But by mixing them, we leave our
code at the mercy of driver bugs.*/
if (beingShutdown != JNI_TRUE) {
"GDIWindowSurfaceData: bounds changed");
}
return SD_FAILURE;
}
if (!safe_ExceptionOccurred(env)) {
}
return SD_FAILURE;
}
if (beingShutdown != JNI_TRUE) {
}
return SD_FAILURE;
}
if (lockflags & SD_LOCK_RD_WR) {
// Do an initial clip to the client region of the window
// Translate to window coords
}
}
}
}
if (lockflags & SD_LOCK_FASTEST) {
ret = SD_SLOWLOCK;
}
} else {
ret = SD_FAILURE;
"GDIWinSD_Lock: error locking by DIB");
}
} else {
/* They didn't lock for anything - we won't give them anything */
ret = SD_FAILURE;
}
return ret;
}
{
return;
}
int x, y, w, h;
// do not subtract insets from x,y as we take care of it in SD_GetDC
struct tagBitmapheader {
union {
} colors;
} bmi;
// Need to create bitmap if we don't have one already or
// if the existing one is not large enough for this operation
// or if we are in 8 bpp display mode (because we need to
// make sure that the latest palette info gets loaded into
// the bitmap)
// REMIND: we should find some way to dynamically force bitmap
// recreation only when the palette changes
{
// delete old objects
"GDIWinSD_GetRasInfo: recreating GDI bitmap");
}
}
// 1,3 byte use BI_RGB, 2,4 byte use BI_BITFIELD...
(pixelStride & 1)
? BI_RGB
: BI_BITFIELDS;
if (pixelStride == 1) {
// we can use systemEntries here because
// RGBQUAD is xRGB and systemEntries are stored as xRGB
} else {
// For non-index cases, init the masks for the pixel depth
for (int i = 0; i < 3; i++) {
}
}
// REMIND: This would be better if moved to the Lock function
// so that errors could be dealt with.
// scanStride is cached along with reuseable bitmap
// Round up to the next DWORD boundary
} else {
}
}
}
if (lockflags & SD_LOCK_NEED_PIXELS) {
::GdiFlush();
}
wsdo->x = x;
wsdo->y = y;
wsdo->w = w;
wsdo->h = h;
y*wsdo->bmScanStride);
pRasInfo->pixelBitOffset = 0;
if (lockflags & SD_LOCK_WRITE) {
// If the user writes to the bitmap then we should
// copy the bitmap to the screen during Unlock
}
} else {
pRasInfo->pixelStride = 0;
pRasInfo->pixelBitOffset = 0;
pRasInfo->scanStride = 0;
}
} else {
/* They didn't lock for anything - we won't give them anything */
pRasInfo->pixelStride = 0;
pRasInfo->pixelBitOffset = 0;
pRasInfo->scanStride = 0;
}
} else {
}
} else {
}
} else {
}
}
{
// Call SetupTGI to ensure that this thread already has a DC that is
// compatible with this window. This means that we won't be calling
// ::SendMessage(GETDC) in the middle of a lock procedure, which creates
// a potential deadlock situation.
// Note that calling SetupTGI here means that anybody needing a DC
// later in this rendering process need only call GetTGI, which
}
{
if (!safe_ExceptionOccurred(env)) {
"Unmatched unlock on Win32 SurfaceData");
}
return;
}
"GDIWinSD_Unlock: do Blt of the bitmap");
// Don't bother copying to screen if our window has gone away
// or if the bitmap was not actually written to during this
::GdiFlush();
}
}
}
}
/*
* REMIND: This mechanism is just a prototype of a way to manage a
* small cache of DC objects. It is incomplete in the following ways:
*
* - It is not thread-safe! It needs appropriate locking and release calls
* (perhaps the AutoDC mechanisms from Kestrel)
* - It does hardly any error checking (What if GetDCEx returns NULL?)
* - It cannot handle printer DCs and their resolution
* - It should probably "live" in the native SurfaceData object to allow
* alternate implementations for printing and embedding
* - It doesn't handle XOR
* - It caches the client bounds to determine if clipping is really needed
* (no way to invalidate the cached bounds and there is probably a better
* way to manage clip validation in any case)
*/
int g = (77 *(c & 0xFF) +
150*((c >> 8) & 0xFF) +
29 *((c >> 16) & 0xFF) + 128) / 256;
c = g | (g << 8) | (g << 16);
}
return COLORFOR(c);
}
{
if (beingShutdown != JNI_TRUE) {
}
}
}
{
// init clip
}
}
// return; // REMIND: What to do here?
}
if (Region_IsEmpty(&clipInfo)) {
::DeleteObject(hrgn);
} else if (Region_IsRectangular(&clipInfo)) {
{
}
} else {
// Make the window-relative rect a client-relative
// one for Windows
::DeleteObject(hrgn);
}
} else {
pRect++;
}
::DeleteObject(hrgn);
}
}
}
// init composite
}
} else {
}
}
}
}
// init brush and pen
}
}
}
}
}
}
}
}
}
}
}
}
}
{
// Don't actually do anything here: every thread holds its own
// wsdo-specific DC until the thread goes away or the wsdo
// is disposed.
}
{
}
/*
* Method: GDIWinSD_Dispose
*/
static void
{
// ops is assumed non-null as it is checked in SurfaceData_DisposeOps
// delete old objects
}
}
}
delete wsdo->surfaceLock;
}
/*
* Class: sun_java2d_windows_GDIWindowSurfaceData
* Method: invalidateSD
* Signature: ()V
*/
{
}
}