1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
|
/* 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;
}
|