/*
* 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.
*/
#ifndef HEADLESS
#include <jni.h>
#include <jlong.h>
#include "SurfaceData.h"
#include "OGLBlitLoops.h"
#include "OGLRenderQueue.h"
#include "OGLSurfaceData.h"
#include "GraphicsPrimitiveMgr.h"
extern OGLPixelFormat PixelFormats[];
/**
* Inner loop used for copying a source OpenGL "Surface" (window, pbuffer,
* etc.) to a destination OpenGL "Surface". Note that the same surface can
* be used as both the source and destination, as is the case in a copyArea()
* operation. This method is invoked from OGLBlitLoops_IsoBlit() as well as
* OGLBlitLoops_CopyArea().
*
* The standard glCopyPixels() mechanism is used to copy the source region
* into the destination region. If the regions have different dimensions,
* the source will be scaled into the destination as appropriate (only
* nearest neighbor filtering will be applied for simple scale operations).
*/
static void
{
// the following lines account for the fact that glCopyPixels() copies a
// region whose lower-left corner is at (x,y), but the source parameters
// (sx1,sy1) we are given here point to the upper-left corner of the
// source region... so here we play with the sy1 and dy1 parameters so
// that they point to the lower-left corners of the regions...
}
// see OGLBlitSwToSurface() for more info on the following two lines
j2d_glRasterPos2i(0, 0);
} else {
}
OGLContext_SetExtraAlpha(1.0f);
}
}
/**
* Inner loop used for copying a source OpenGL "Texture" to a destination
* OpenGL "Surface". This method is invoked from OGLBlitLoops_IsoBlit().
*
* This method will copy, scale, or transform the source texture into the
* destination depending on the transform state, as established in
* and OGLContext_SetTransform(). If the source texture is
* transformed in any way when rendered into the destination, the filtering
* method applied is determined by the hint parameter (can be GL_NEAREST or
* GL_LINEAR).
*/
static void
{
if (rtt) {
/*
* The source is a render-to-texture surface. These surfaces differ
* from regular texture objects in that the bottom scanline (of
* the actual image content) coincides with the top edge of the
* coordinates relative to the top scanline of the image content.
*
* In texture coordinates, the top-left corner of the image content
* would be at:
* while the bottom-right corner corresponds to:
*/
}
// The GL_ARB_texture_rectangle extension requires that we specify
// texture coordinates in the range [0,srcw] and [0,srch] instead of
// [0,1] as we would normally do in the case of GL_TEXTURE_2D
} else {
// Otherwise we need to convert the source bounds into the range [0,1]
}
// Note that we call CHECK_PREVIOUS_OP(texTarget) in IsoBlit(), which
// will call glEnable(texTarget) as necessary.
j2d_glEnd();
}
/**
* Inner loop used for copying a source system memory ("Sw") surface to a
* destination OpenGL "Surface". This method is invoked from
* OGLBlitLoops_Blit().
*
* The standard glDrawPixels() mechanism is used to copy the source region
* into the destination region. If the regions have different
* dimensions, the source will be scaled into the destination
* as appropriate (only nearest neighbor filtering will be applied for simple
* scale operations).
*/
static void
{
}
// if the source surface does not have an alpha channel,
// we need to ensure that the alpha values are forced to
// the current extra alpha value (see OGLContext_SetExtraAlpha()
// for more information)
}
// This is a rather intriguing (yet totally valid) hack... If we were to
// specify a raster position that is outside the surface bounds, the raster
// position would be invalid and nothing would be rendered. However, we
// can use a widely known trick to move the raster position outside the
// surface bounds while maintaining its status as valid. The following
// call to glBitmap() renders a no-op bitmap, but offsets the current
// raster position from (0,0) to the desired location of (dx1,-dy1)...
j2d_glRasterPos2i(0, 0);
// in case pixel stride is not a multiple of scanline stride the copy
// has to be done line by line (see 6207877)
while (height > 0) {
height--;
}
} else {
}
OGLContext_SetExtraAlpha(1.0f);
}
}
}
/**
* Inner loop used for copying a source system memory ("Sw") surface or
* OpenGL "Surface" to a destination OpenGL "Surface", using an OpenGL texture
* tile as an intermediate surface. This method is invoked from
* OGLBlitLoops_Blit() for "Sw" surfaces and OGLBlitLoops_IsoBlit() for
* "Surface" surfaces.
*
* This method is used to transform the source surface into the destination.
* Pixel rectangles cannot be arbitrarily transformed (without the
* GL_EXT_pixel_transform extension, which is not supported on most modern
* hardware). However, texture mapped quads do respect the GL_MODELVIEW
* transform matrix, so we use textures here to perform the transform
* operation. This method uses a tile-based approach in which a small
* subregion of the source surface is copied into a cached texture tile. The
* texture tile is then mapped into the appropriate location in the
* destination surface.
*
* REMIND: this only works well using GL_NEAREST for the filtering mode
* (GL_LINEAR causes visible stitching problems between tiles,
* but this can be fixed by making use of texture borders)
*/
static void
{
if (oglc->blitTextureID == 0) {
if (!OGLContext_InitBlitTileTexture(oglc)) {
"OGLBlitToSurfaceViaTexture: could not init blit tile");
return;
}
}
tx1 = 0.0f;
ty1 = 0.0f;
if (adjustAlpha) {
// if the source surface does not have an alpha channel,
// we need to ensure that the alpha values are forced to 1.0f
}
// in case pixel stride is not a multiple of scanline stride the copy
// has to be done line by line (see 6207877)
if (swsurface) {
if (slowPath) {
while (tmph > 0) {
pSrc);
tmph--;
}
} else {
}
// the texture image is "right side up", so we align the
// upper-left texture corner with the upper-left quad corner
j2d_glEnd();
} else {
// this accounts for lower-left origin of the source region
// the texture image is "upside down" after the last step, so
// we align the bottom-left texture corner with the upper-left
// quad corner (and vice versa) to effectively flip the
// texture image
j2d_glEnd();
}
}
}
if (adjustAlpha) {
}
}
/**
* Inner loop used for copying a source system memory ("Sw") surface to a
* destination OpenGL "Texture". This method is invoked from
* OGLBlitLoops_Blit().
*
* The source surface is effectively loaded into the OpenGL texture object,
* which must have already been initialized by OGLSD_initTexture(). Note
* that this method is only capable of copying the source surface into the
* destination surface (i.e. no scaling or general transform is allowed).
* This restriction should not be an issue as this method is only used
* currently to cache a static system memory image into an OpenGL texture in
* a hidden-acceleration situation.
*/
static void
{
if (adjustAlpha) {
// if the source surface does not have an alpha channel,
// we need to ensure that the alpha values are forced to 1.0f
}
// in case pixel stride is not a multiple of scanline stride the copy
// has to be done line by line (see 6207877)
while (height > 0) {
height--;
}
} else {
}
if (adjustAlpha) {
}
}
/**
* General blit method for copying a native OpenGL surface (of type "Surface"
* or "Texture") to another OpenGL "Surface". If texture is JNI_TRUE, this
* method will invoke the Texture->Surface inner loop; otherwise, one of the
* Surface->Surface inner loops will be invoked, depending on the transform
* state.
*
* REMIND: we can trick these blit methods into doing XOR simply by passing
* in the (pixel ^ xorpixel) as the pixel value and preceding the
* blit with a fillrect...
*/
void
{
"OGLBlitLoops_IsoBlit: invalid dimensions");
return;
}
{
}
}
}
}
if (texture) {
} else {
if (xform) {
// we must use the via-texture codepath when there is a xform
} else {
// look at the vendor to see which codepath is faster
// (this has been empirically determined; see 5020009)
switch (OGLC_GET_VENDOR(oglc)) {
case OGLC_VENDOR_NVIDIA:
// the via-texture codepath tends to be faster when
// there is either a simple scale OR an extra alpha
break;
case OGLC_VENDOR_ATI:
// the via-texture codepath tends to be faster only when
// there is an extra alpha involved (scaling or not)
break;
default:
// just use the glCopyPixels() codepath
break;
}
}
if (viaTexture) {
} else {
}
}
}
}
/**
* General blit method for copying a system memory ("Sw") surface to a native
* OpenGL surface (of type "Surface" or "Texture"). If texture is JNI_TRUE,
* this method will invoke the Sw->Texture inner loop; otherwise, one of the
* Sw->Surface inner loops will be invoked, depending on the transform state.
*/
void
{
"OGLBlitLoops_Blit: invalid dimensions or srctype");
return;
}
"OGLBlitLoops_Blit: could not acquire lock");
return;
}
{
}
}
}
}
if (texture) {
// These coordinates will always be integers since we
// only ever do a straight copy from sw to texture.
// Thus these casts are "safe" - no loss of precision.
} else {
if (xform) {
// we must use the via-texture codepath when there
// is a xform
} else {
// look at the vendor to see which codepath is faster
// (this has been empirically determined; see 5020009)
switch (OGLC_GET_VENDOR(oglc)) {
case OGLC_VENDOR_NVIDIA:
// the via-texture codepath tends to be faster when
// there is either a simple scale OR an extra alpha
break;
default:
// just use the glDrawPixels() codepath
break;
}
}
if (viaTexture) {
} else {
}
}
}
}
}
/**
* Specialized blit method for copying a native OpenGL "Surface" (pbuffer,
* window, etc.) to a system memory ("Sw") surface.
*/
void
{
"OGLBlitLoops_SurfaceToSwBlit: dimensions are non-positive");
return;
}
"OGLBlitLoops_SurfaceToSwBlit: could not acquire dst lock");
return;
}
{
#ifdef MACOSX
// For some reason Apple's OpenGL implementation will
// read back zero values from the alpha channel of an
// opaque surface when using glReadPixels(), so here we
// force the resulting pixels to be fully opaque.
}
#endif
// this accounts for lower-left origin of the source region
// we must read one scanline at a time because there is no way
// to read starting at the top-left corner of the source region
while (height > 0) {
srcy--;
dsty++;
height--;
}
#ifdef MACOSX
}
#endif
}
}
}
void
{
// some bugs in Sun's and Apple's OpenGL implementations
// (it's a good idea to restrict the source parameters anyway, since
// passing out of range parameters to glCopyPixels() will result in
// an OpenGL error)
#ifdef MACOSX
// For some reason Apple's OpenGL implementation will fail
// overlapping and glColorMask() has disabled writes to the
// alpha channel. The workaround is to temporarily re-enable
// the alpha channel during the glCopyPixels() operation.
}
#endif
#ifdef MACOSX
}
#endif
}
}
#endif /* !HEADLESS */