Path: blob/master/src/java.desktop/share/native/libawt/java2d/pipe/BufferedMaskBlit.c
41159 views
/*1* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <jni.h>26#include <jlong.h>27#include <jni_util.h>28#include "sun_java2d_pipe_BufferedMaskBlit.h"29#include "sun_java2d_pipe_BufferedOpCodes.h"30#include "Trace.h"31#include "GraphicsPrimitiveMgr.h"32#include "IntArgb.h"33#include "IntRgb.h"34#include "IntBgr.h"3536#define MAX_MASK_LENGTH (32 * 32)37extern unsigned char mul8table[256][256];3839/**40* This implementation of MaskBlit first combines the source system memory41* tile with the corresponding alpha mask and stores the resulting42* IntArgbPre pixels directly into the RenderBuffer. Those pixels are43* then eventually pulled off the RenderBuffer and copied to the destination44* surface in OGL/D3DMaskBlit.45*46* Note that currently there are only inner loops defined for IntArgb,47* IntArgbPre, IntRgb, and IntBgr, as those are the most commonly used48* formats for this operation.49*/50JNIEXPORT jint JNICALL51Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile52(JNIEnv *env, jobject mb,53jlong buf, jint bpos,54jobject srcData, jlong pSrcOps, jint srcType,55jbyteArray maskArray, jint masklen, jint maskoff, jint maskscan,56jint srcx, jint srcy, jint dstx, jint dsty,57jint width, jint height)58{59SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);60SurfaceDataRasInfo srcInfo;61unsigned char *bbuf;62jint *pBuf;6364J2dTraceLn1(J2D_TRACE_INFO,65"BufferedMaskBlit_enqueueTile: bpos=%d",66bpos);6768if (srcOps == NULL) {69J2dRlsTraceLn(J2D_TRACE_ERROR,70"BufferedMaskBlit_enqueueTile: srcOps is null");71return bpos;72}7374bbuf = (unsigned char *)jlong_to_ptr(buf);75if (bbuf == NULL) {76J2dRlsTraceLn(J2D_TRACE_ERROR,77"BufferedMaskBlit_enqueueTile: cannot get direct buffer address");78return bpos;79}80pBuf = (jint *)(bbuf + bpos);8182if (JNU_IsNull(env, maskArray)) {83J2dRlsTraceLn(J2D_TRACE_ERROR,84"BufferedMaskBlit_enqueueTile: mask array is null");85return bpos;86}8788if (masklen > MAX_MASK_LENGTH) {89// REMIND: this approach is seriously flawed if the mask90// length is ever greater than MAX_MASK_LENGTH (won't fit91// into the cached mask tile); so far this hasn't92// been a problem though...93J2dRlsTraceLn(J2D_TRACE_ERROR,94"BufferedMaskBlit_enqueueTile: mask array too large");95return bpos;96}9798srcInfo.bounds.x1 = srcx;99srcInfo.bounds.y1 = srcy;100srcInfo.bounds.x2 = srcx + width;101srcInfo.bounds.y2 = srcy + height;102103if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {104J2dRlsTraceLn(J2D_TRACE_WARNING,105"BufferedMaskBlit_enqueueTile: could not acquire lock");106return bpos;107}108109if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&110srcInfo.bounds.y2 > srcInfo.bounds.y1)111{112srcOps->GetRasInfo(env, srcOps, &srcInfo);113if (srcInfo.rasBase) {114jint h;115jint srcScanStride = srcInfo.scanStride;116jint srcPixelStride = srcInfo.pixelStride;117jint *pSrc = (jint *)118PtrCoord(srcInfo.rasBase,119srcInfo.bounds.x1, srcInfo.pixelStride,120srcInfo.bounds.y1, srcInfo.scanStride);121unsigned char *pMask, *pMaskAlloc;122pMask = pMaskAlloc =123(*env)->GetPrimitiveArrayCritical(env, maskArray, 0);124if (pMask == NULL) {125J2dRlsTraceLn(J2D_TRACE_ERROR,126"BufferedMaskBlit_enqueueTile: cannot lock mask array");127SurfaceData_InvokeRelease(env, srcOps, &srcInfo);128SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);129return bpos;130}131132width = srcInfo.bounds.x2 - srcInfo.bounds.x1;133height = srcInfo.bounds.y2 - srcInfo.bounds.y1;134maskoff += ((srcInfo.bounds.y1 - srcy) * maskscan +135(srcInfo.bounds.x1 - srcx));136maskscan -= width;137pMask += maskoff;138srcScanStride -= width * srcPixelStride;139h = height;140141J2dTraceLn4(J2D_TRACE_VERBOSE,142" sx=%d sy=%d w=%d h=%d",143srcInfo.bounds.x1, srcInfo.bounds.y1, width, height);144J2dTraceLn2(J2D_TRACE_VERBOSE,145" maskoff=%d maskscan=%d",146maskoff, maskscan);147J2dTraceLn2(J2D_TRACE_VERBOSE,148" pixstride=%d scanstride=%d",149srcPixelStride, srcScanStride);150151// enqueue parameters152pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT;153pBuf[1] = dstx;154pBuf[2] = dsty;155pBuf[3] = width;156pBuf[4] = height;157pBuf += 5;158bpos += 5 * sizeof(jint);159160// apply alpha values from mask to the source tile, and store161// resulting IntArgbPre pixels into RenderBuffer (there are162// separate inner loops for the most common source formats)163switch (srcType) {164case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB:165do {166jint w = width;167do {168jint pathA = *pMask++;169if (!pathA) {170pBuf[0] = 0;171} else {172jint pixel = pSrc[0];173if (pathA == 0xff && (pixel >> 24) + 1 == 0) {174pBuf[0] = pixel;175} else {176jint r, g, b, a;177ExtractIntDcmComponents1234(pixel, a, r, g, b);178a = MUL8(pathA, a);179r = MUL8(a, r);180g = MUL8(a, g);181b = MUL8(a, b);182pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;183}184}185pSrc = PtrAddBytes(pSrc, srcPixelStride);186pBuf++;187} while (--w > 0);188pSrc = PtrAddBytes(pSrc, srcScanStride);189pMask = PtrAddBytes(pMask, maskscan);190} while (--h > 0);191break;192193case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB_PRE:194do {195jint w = width;196do {197jint pathA = *pMask++;198if (!pathA) {199pBuf[0] = 0;200} else if (pathA == 0xff) {201pBuf[0] = pSrc[0];202} else {203jint r, g, b, a;204a = MUL8(pathA, (pSrc[0] >> 24) & 0xff);205r = MUL8(pathA, (pSrc[0] >> 16) & 0xff);206g = MUL8(pathA, (pSrc[0] >> 8) & 0xff);207b = MUL8(pathA, (pSrc[0] >> 0) & 0xff);208pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;209}210pSrc = PtrAddBytes(pSrc, srcPixelStride);211pBuf++;212} while (--w > 0);213pSrc = PtrAddBytes(pSrc, srcScanStride);214pMask = PtrAddBytes(pMask, maskscan);215} while (--h > 0);216break;217218case sun_java2d_pipe_BufferedMaskBlit_ST_INT_RGB:219do {220jint w = width;221do {222jint pathA = *pMask++;223if (!pathA) {224pBuf[0] = 0;225} else if (pathA == 0xff) {226pBuf[0] = pSrc[0] | 0xff000000;227} else {228jint r, g, b, a;229LoadIntRgbTo3ByteRgb(pSrc, c, 0, r, g, b);230a = pathA;231r = MUL8(a, r);232g = MUL8(a, g);233b = MUL8(a, b);234pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;235}236pSrc = PtrAddBytes(pSrc, srcPixelStride);237pBuf++;238} while (--w > 0);239pSrc = PtrAddBytes(pSrc, srcScanStride);240pMask = PtrAddBytes(pMask, maskscan);241} while (--h > 0);242break;243244case sun_java2d_pipe_BufferedMaskBlit_ST_INT_BGR:245do {246jint w = width;247do {248jint pathA = *pMask++;249if (!pathA) {250pBuf[0] = 0;251} else {252jint r, g, b, a;253LoadIntBgrTo3ByteRgb(pSrc, c, 0, r, g, b);254a = pathA;255r = MUL8(a, r);256g = MUL8(a, g);257b = MUL8(a, b);258pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;259}260pSrc = PtrAddBytes(pSrc, srcPixelStride);261pBuf++;262} while (--w > 0);263pSrc = PtrAddBytes(pSrc, srcScanStride);264pMask = PtrAddBytes(pMask, maskscan);265} while (--h > 0);266break;267268default:269// should not get here, just no-op...270break;271}272273// increment current byte position274bpos += width * height * sizeof(jint);275276(*env)->ReleasePrimitiveArrayCritical(env, maskArray,277pMaskAlloc, JNI_ABORT);278}279SurfaceData_InvokeRelease(env, srcOps, &srcInfo);280}281SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);282283// return the current byte position284return bpos;285}286287288