0N/A/*
3909N/A * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <jni.h>
0N/A#include <jlong.h>
0N/A#include <jni_util.h>
0N/A#include "sun_java2d_pipe_BufferedMaskBlit.h"
0N/A#include "sun_java2d_pipe_BufferedOpCodes.h"
0N/A#include "Trace.h"
0N/A#include "GraphicsPrimitiveMgr.h"
0N/A#include "IntArgb.h"
0N/A#include "IntRgb.h"
0N/A#include "IntBgr.h"
0N/A
0N/A#define MAX_MASK_LENGTH (32 * 32)
0N/Aextern unsigned char mul8table[256][256];
0N/A
0N/A/**
0N/A * This implementation of MaskBlit first combines the source system memory
0N/A * tile with the corresponding alpha mask and stores the resulting
0N/A * IntArgbPre pixels directly into the RenderBuffer. Those pixels are
0N/A * then eventually pulled off the RenderBuffer and copied to the destination
0N/A * surface in OGL/D3DMaskBlit.
0N/A *
0N/A * Note that currently there are only inner loops defined for IntArgb,
0N/A * IntArgbPre, IntRgb, and IntBgr, as those are the most commonly used
0N/A * formats for this operation.
0N/A */
0N/AJNIEXPORT jint JNICALL
0N/AJava_sun_java2d_pipe_BufferedMaskBlit_enqueueTile
0N/A (JNIEnv *env, jobject mb,
0N/A jlong buf, jint bpos,
0N/A jobject srcData, jlong pSrcOps, jint srcType,
0N/A jbyteArray maskArray, jint masklen, jint maskoff, jint maskscan,
0N/A jint srcx, jint srcy, jint dstx, jint dsty,
0N/A jint width, jint height)
0N/A{
0N/A SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
0N/A SurfaceDataRasInfo srcInfo;
0N/A unsigned char *bbuf;
0N/A jint *pBuf;
0N/A
0N/A J2dTraceLn1(J2D_TRACE_INFO,
0N/A "BufferedMaskBlit_enqueueTile: bpos=%d",
0N/A bpos);
0N/A
0N/A if (srcOps == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "BufferedMaskBlit_enqueueTile: srcOps is null");
0N/A return bpos;
0N/A }
0N/A
0N/A bbuf = (unsigned char *)jlong_to_ptr(buf);
0N/A if (bbuf == NULL) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "BufferedMaskBlit_enqueueTile: cannot get direct buffer address");
0N/A return bpos;
0N/A }
0N/A pBuf = (jint *)(bbuf + bpos);
0N/A
0N/A if (JNU_IsNull(env, maskArray)) {
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "BufferedMaskBlit_enqueueTile: mask array is null");
0N/A return bpos;
0N/A }
0N/A
0N/A if (masklen > MAX_MASK_LENGTH) {
0N/A // REMIND: this approach is seriously flawed if the mask
0N/A // length is ever greater than MAX_MASK_LENGTH (won't fit
0N/A // into the cached mask tile); so far this hasn't
0N/A // been a problem though...
0N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
0N/A "BufferedMaskBlit_enqueueTile: mask array too large");
0N/A return bpos;
0N/A }
0N/A
0N/A srcInfo.bounds.x1 = srcx;
0N/A srcInfo.bounds.y1 = srcy;
0N/A srcInfo.bounds.x2 = srcx + width;
0N/A srcInfo.bounds.y2 = srcy + height;
0N/A
0N/A if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
0N/A J2dRlsTraceLn(J2D_TRACE_WARNING,
0N/A "BufferedMaskBlit_enqueueTile: could not acquire lock");
0N/A return bpos;
0N/A }
0N/A
0N/A if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
0N/A srcInfo.bounds.y2 > srcInfo.bounds.y1)
0N/A {
0N/A srcOps->GetRasInfo(env, srcOps, &srcInfo);
0N/A if (srcInfo.rasBase) {
0N/A jint h;
0N/A jint srcScanStride = srcInfo.scanStride;
0N/A jint srcPixelStride = srcInfo.pixelStride;
0N/A jint *pSrc = (jint *)
0N/A PtrCoord(srcInfo.rasBase,
0N/A srcInfo.bounds.x1, srcInfo.pixelStride,
0N/A srcInfo.bounds.y1, srcInfo.scanStride);
3272N/A unsigned char *pMask, *pMaskAlloc;
3272N/A pMask = pMaskAlloc =
430N/A (*env)->GetPrimitiveArrayCritical(env, maskArray, 0);
430N/A if (pMask == NULL) {
430N/A J2dRlsTraceLn(J2D_TRACE_ERROR,
430N/A "BufferedMaskBlit_enqueueTile: cannot lock mask array");
430N/A SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
430N/A SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
430N/A return bpos;
430N/A }
0N/A
0N/A width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
0N/A height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
0N/A maskoff += ((srcInfo.bounds.y1 - srcy) * maskscan +
0N/A (srcInfo.bounds.x1 - srcx));
0N/A maskscan -= width;
0N/A pMask += maskoff;
0N/A srcScanStride -= width * srcPixelStride;
0N/A h = height;
0N/A
0N/A J2dTraceLn4(J2D_TRACE_VERBOSE,
0N/A " sx=%d sy=%d w=%d h=%d",
0N/A srcInfo.bounds.x1, srcInfo.bounds.y1, width, height);
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE,
0N/A " maskoff=%d maskscan=%d",
0N/A maskoff, maskscan);
0N/A J2dTraceLn2(J2D_TRACE_VERBOSE,
0N/A " pixstride=%d scanstride=%d",
0N/A srcPixelStride, srcScanStride);
0N/A
0N/A // enqueue parameters
0N/A pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT;
0N/A pBuf[1] = dstx;
0N/A pBuf[2] = dsty;
0N/A pBuf[3] = width;
0N/A pBuf[4] = height;
0N/A pBuf += 5;
0N/A bpos += 5 * sizeof(jint);
0N/A
0N/A // apply alpha values from mask to the source tile, and store
0N/A // resulting IntArgbPre pixels into RenderBuffer (there are
0N/A // separate inner loops for the most common source formats)
0N/A switch (srcType) {
0N/A case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB:
0N/A do {
0N/A jint w = width;
0N/A do {
430N/A jint pathA = *pMask++;
0N/A if (!pathA) {
0N/A pBuf[0] = 0;
0N/A } else {
430N/A jint pixel = pSrc[0];
430N/A if (pathA == 0xff && (pixel >> 24) + 1 == 0) {
430N/A pBuf[0] = pixel;
430N/A } else {
430N/A jint r, g, b, a;
430N/A ExtractIntDcmComponents1234(pixel, a, r, g, b);
430N/A a = MUL8(pathA, a);
430N/A r = MUL8(a, r);
430N/A g = MUL8(a, g);
430N/A b = MUL8(a, b);
430N/A pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
430N/A }
0N/A }
0N/A pSrc = PtrAddBytes(pSrc, srcPixelStride);
0N/A pBuf++;
0N/A } while (--w > 0);
0N/A pSrc = PtrAddBytes(pSrc, srcScanStride);
0N/A pMask = PtrAddBytes(pMask, maskscan);
0N/A } while (--h > 0);
0N/A break;
0N/A
0N/A case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB_PRE:
0N/A do {
0N/A jint w = width;
0N/A do {
430N/A jint pathA = *pMask++;
0N/A if (!pathA) {
0N/A pBuf[0] = 0;
0N/A } else if (pathA == 0xff) {
0N/A pBuf[0] = pSrc[0];
0N/A } else {
430N/A jint r, g, b, a;
430N/A a = MUL8(pathA, (pSrc[0] >> 24) & 0xff);
430N/A r = MUL8(pathA, (pSrc[0] >> 16) & 0xff);
430N/A g = MUL8(pathA, (pSrc[0] >> 8) & 0xff);
430N/A b = MUL8(pathA, (pSrc[0] >> 0) & 0xff);
0N/A pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
0N/A }
0N/A pSrc = PtrAddBytes(pSrc, srcPixelStride);
0N/A pBuf++;
0N/A } while (--w > 0);
0N/A pSrc = PtrAddBytes(pSrc, srcScanStride);
0N/A pMask = PtrAddBytes(pMask, maskscan);
0N/A } while (--h > 0);
0N/A break;
0N/A
0N/A case sun_java2d_pipe_BufferedMaskBlit_ST_INT_RGB:
0N/A do {
0N/A jint w = width;
0N/A do {
430N/A jint pathA = *pMask++;
0N/A if (!pathA) {
0N/A pBuf[0] = 0;
430N/A } else if (pathA == 0xff) {
430N/A pBuf[0] = pSrc[0] | 0xff000000;
0N/A } else {
430N/A jint r, g, b, a;
430N/A LoadIntRgbTo3ByteRgb(pSrc, c, 0, r, g, b);
0N/A a = pathA;
430N/A r = MUL8(a, r);
430N/A g = MUL8(a, g);
430N/A b = MUL8(a, b);
0N/A pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
0N/A }
0N/A pSrc = PtrAddBytes(pSrc, srcPixelStride);
0N/A pBuf++;
0N/A } while (--w > 0);
0N/A pSrc = PtrAddBytes(pSrc, srcScanStride);
0N/A pMask = PtrAddBytes(pMask, maskscan);
0N/A } while (--h > 0);
0N/A break;
0N/A
0N/A case sun_java2d_pipe_BufferedMaskBlit_ST_INT_BGR:
0N/A do {
0N/A jint w = width;
0N/A do {
430N/A jint pathA = *pMask++;
0N/A if (!pathA) {
0N/A pBuf[0] = 0;
0N/A } else {
430N/A jint r, g, b, a;
430N/A LoadIntBgrTo3ByteRgb(pSrc, c, 0, r, g, b);
0N/A a = pathA;
430N/A r = MUL8(a, r);
430N/A g = MUL8(a, g);
430N/A b = MUL8(a, b);
0N/A pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
0N/A }
0N/A pSrc = PtrAddBytes(pSrc, srcPixelStride);
0N/A pBuf++;
0N/A } while (--w > 0);
0N/A pSrc = PtrAddBytes(pSrc, srcScanStride);
0N/A pMask = PtrAddBytes(pMask, maskscan);
0N/A } while (--h > 0);
0N/A break;
0N/A
0N/A default:
0N/A // should not get here, just no-op...
0N/A break;
0N/A }
0N/A
0N/A // increment current byte position
0N/A bpos += width * height * sizeof(jint);
430N/A
430N/A (*env)->ReleasePrimitiveArrayCritical(env, maskArray,
3272N/A pMaskAlloc, JNI_ABORT);
0N/A }
0N/A SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
0N/A }
0N/A SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
0N/A
0N/A // return the current byte position
0N/A return bpos;
0N/A}