You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.6 KiB
217 lines
6.6 KiB
/* libs/pixelflinger/raster.cpp |
|
** |
|
** Copyright 2006, The Android Open Source Project |
|
** |
|
** Licensed under the Apache License, Version 2.0 (the "License"); |
|
** you may not use this file except in compliance with the License. |
|
** You may obtain a copy of the License at |
|
** |
|
** http://www.apache.org/licenses/LICENSE-2.0 |
|
** |
|
** Unless required by applicable law or agreed to in writing, software |
|
** distributed under the License is distributed on an "AS IS" BASIS, |
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
** See the License for the specific language governing permissions and |
|
** limitations under the License. |
|
*/ |
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
#include "raster.h" |
|
#include "trap.h" |
|
|
|
namespace android { |
|
|
|
static void ggl_rasterPos2x(void* con, GGLfixed x, GGLfixed y); |
|
static void ggl_rasterPos2i(void* con, GGLint x, GGLint y); |
|
static void ggl_copyPixels(void* con, GGLint xs, GGLint ys, |
|
GGLsizei width, GGLsizei height, GGLenum type); |
|
|
|
void ggl_init_raster(context_t* c) |
|
{ |
|
GGLContext& procs = *(GGLContext*)c; |
|
GGL_INIT_PROC(procs, copyPixels); |
|
GGL_INIT_PROC(procs, rasterPos2x); |
|
GGL_INIT_PROC(procs, rasterPos2i); |
|
} |
|
|
|
void ggl_rasterPos2x(void* con, GGLfixed x, GGLfixed y) |
|
{ |
|
GGL_CONTEXT(c, con); |
|
// raster pos should be processed just like glVertex |
|
c->state.raster.x = x; |
|
c->state.raster.y = y; |
|
} |
|
|
|
void ggl_rasterPos2i(void* con, GGLint x, GGLint y) |
|
{ |
|
ggl_rasterPos2x(con, gglIntToFixed(x), gglIntToFixed(y)); |
|
} |
|
|
|
void ggl_copyPixels(void* con, GGLint xs, GGLint ys, |
|
GGLsizei width, GGLsizei height, GGLenum /*type*/) |
|
{ |
|
GGL_CONTEXT(c, con); |
|
|
|
// color-buffer |
|
surface_t* cb = &(c->state.buffers.color); |
|
|
|
// undefined behaviour if we try to copy from outside the surface |
|
if (uint32_t(xs) > cb->width) |
|
return; |
|
if (uint32_t(ys) > cb->height) |
|
return; |
|
if (uint32_t(xs + width) > cb->width) |
|
return; |
|
if (uint32_t(ys + height) > cb->height) |
|
return; |
|
|
|
// copy to current raster position |
|
GGLint xd = gglFixedToIntRound(c->state.raster.x); |
|
GGLint yd = gglFixedToIntRound(c->state.raster.y); |
|
|
|
// clip to scissor |
|
if (xd < GGLint(c->state.scissor.left)) { |
|
GGLint offset = GGLint(c->state.scissor.left) - xd; |
|
xd = GGLint(c->state.scissor.left); |
|
xs += offset; |
|
width -= offset; |
|
} |
|
if (yd < GGLint(c->state.scissor.top)) { |
|
GGLint offset = GGLint(c->state.scissor.top) - yd; |
|
yd = GGLint(c->state.scissor.top); |
|
ys += offset; |
|
height -= offset; |
|
} |
|
if ((xd + width) > GGLint(c->state.scissor.right)) { |
|
width = GGLint(c->state.scissor.right) - xd; |
|
} |
|
if ((yd + height) > GGLint(c->state.scissor.bottom)) { |
|
height = GGLint(c->state.scissor.bottom) - yd; |
|
} |
|
|
|
if (width<=0 || height<=0) { |
|
return; // nothing to copy |
|
} |
|
|
|
if (xs==xd && ys==yd) { |
|
// nothing to do, but be careful, this might not be true when we support |
|
// gglPixelTransfer, gglPixelMap and gglPixelZoom |
|
return; |
|
} |
|
|
|
const GGLFormat* fp = &(c->formats[cb->format]); |
|
uint8_t* src = reinterpret_cast<uint8_t*>(cb->data) |
|
+ (xs + (cb->stride * ys)) * fp->size; |
|
uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) |
|
+ (xd + (cb->stride * yd)) * fp->size; |
|
const size_t bpr = cb->stride * fp->size; |
|
const size_t rowsize = width * fp->size; |
|
size_t yc = height; |
|
|
|
if (ys < yd) { |
|
// bottom to top |
|
src += height * bpr; |
|
dst += height * bpr; |
|
do { |
|
dst -= bpr; |
|
src -= bpr; |
|
memcpy(dst, src, rowsize); |
|
} while (--yc); |
|
} else { |
|
if (ys == yd) { |
|
// might be right to left |
|
do { |
|
memmove(dst, src, rowsize); |
|
dst += bpr; |
|
src += bpr; |
|
} while (--yc); |
|
} else { |
|
// top to bottom |
|
do { |
|
memcpy(dst, src, rowsize); |
|
dst += bpr; |
|
src += bpr; |
|
} while (--yc); |
|
} |
|
} |
|
} |
|
|
|
}; // namespace android |
|
|
|
using namespace android; |
|
|
|
GGLint gglBitBlit(GGLContext* con, int tmu, GGLint crop[4], GGLint where[4]) |
|
{ |
|
GGL_CONTEXT(c, (void*)con); |
|
|
|
GGLint x = where[0]; |
|
GGLint y = where[1]; |
|
GGLint w = where[2]; |
|
GGLint h = where[3]; |
|
|
|
// exclsively enable this tmu |
|
const GGLSurface& cbSurface = c->state.buffers.color.s; |
|
c->procs.activeTexture(c, tmu); |
|
c->procs.disable(c, GGL_W_LERP); |
|
|
|
uint32_t tmus = 1UL<<tmu; |
|
if (c->state.enabled_tmu != tmus) { |
|
c->activeTMU->enable = 1; |
|
c->state.enabled_tmu = tmus; |
|
c->state.enables |= GGL_ENABLE_TMUS; |
|
ggl_state_changed(c, GGL_TMU_STATE); |
|
} |
|
|
|
const GGLint Wcr = crop[2]; |
|
const GGLint Hcr = crop[3]; |
|
if ((w == Wcr) && (h == Hcr)) { |
|
c->procs.texGeni(c, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); |
|
c->procs.texGeni(c, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE); |
|
const GGLint Ucr = crop[0]; |
|
const GGLint Vcr = crop[1]; |
|
const GGLint s0 = Ucr - x; |
|
const GGLint t0 = Vcr - y; |
|
c->procs.texCoord2i(c, s0, t0); |
|
c->procs.recti(c, x, y, x+w, y+h); |
|
} else { |
|
int32_t texcoords[8]; |
|
x = gglIntToFixed(x); |
|
y = gglIntToFixed(y); |
|
|
|
// we CLAMP here, which works with premultiplied (s,t) |
|
c->procs.texParameteri(c, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); |
|
c->procs.texParameteri(c, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); |
|
c->procs.texGeni(c, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); |
|
c->procs.texGeni(c, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); |
|
|
|
const GGLint Ucr = crop[0] << 16; |
|
const GGLint Vcr = crop[1] << 16; |
|
const GGLint Wcr = crop[2] << 16; |
|
const GGLint Hcr = crop[3] << 16; |
|
|
|
// computes texture coordinates (pre-multiplied) |
|
int32_t dsdx = Wcr / w; // dsdx = ((Wcr/w)/Wt)*Wt |
|
int32_t dtdy = Hcr / h; // dtdy = ((Hcr/h)/Ht)*Ht |
|
int32_t s0 = Ucr - gglMulx(dsdx, x); // s0 = Ucr - x * dsdx |
|
int32_t t0 = Vcr - gglMulx(dtdy, y); // t0 = Vcr - y * dtdy |
|
texcoords[0] = s0; |
|
texcoords[1] = dsdx; |
|
texcoords[2] = 0; |
|
texcoords[3] = t0; |
|
texcoords[4] = 0; |
|
texcoords[5] = dtdy; |
|
texcoords[6] = 0; |
|
texcoords[7] = 0; |
|
c->procs.texCoordGradScale8xv(c, tmu, texcoords); |
|
c->procs.recti(c, |
|
gglFixedToIntRound(x), |
|
gglFixedToIntRound(y), |
|
gglFixedToIntRound(x)+w, |
|
gglFixedToIntRound(y)+h); |
|
} |
|
return 0; |
|
} |
|
|
|
|