diff options
Diffstat (limited to 'libpixelflinger/include/private/pixelflinger/ggl_context.h')
-rw-r--r-- | libpixelflinger/include/private/pixelflinger/ggl_context.h | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/libpixelflinger/include/private/pixelflinger/ggl_context.h b/libpixelflinger/include/private/pixelflinger/ggl_context.h new file mode 100644 index 0000000..d43655c --- /dev/null +++ b/libpixelflinger/include/private/pixelflinger/ggl_context.h @@ -0,0 +1,565 @@ +/* + * Copyright (C) 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. + */ + +#ifndef ANDROID_GGL_CONTEXT_H +#define ANDROID_GGL_CONTEXT_H + +#include <stdint.h> +#include <stddef.h> +#include <string.h> +#include <sys/types.h> +#include <endian.h> + +#include <pixelflinger/pixelflinger.h> +#include <private/pixelflinger/ggl_fixed.h> + +namespace android { + +// ---------------------------------------------------------------------------- + +#if BYTE_ORDER == LITTLE_ENDIAN + +inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { + return v; +} +inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { + return v; +} + +#else + +inline uint32_t GGL_RGBA_TO_HOST(uint32_t v) { +#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 + uint32_t r; + __asm__("wsbh %0, %1;" + "rotr %0, %0, 16" + : "=r" (r) + : "r" (v) + ); + return r; +#else + return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); +#endif +} +inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { +#if defined(__mips__) && __mips==32 && __mips_isa_rev>=2 + uint32_t r; + __asm__("wsbh %0, %1;" + "rotr %0, %0, 16" + : "=r" (r) + : "r" (v) + ); + return r; +#else + return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); +#endif +} + +#endif + +// ---------------------------------------------------------------------------- + +const int GGL_DITHER_BITS = 6; // dither weights stored on 6 bits +const int GGL_DITHER_ORDER_SHIFT= 3; +const int GGL_DITHER_ORDER = (1<<GGL_DITHER_ORDER_SHIFT); +const int GGL_DITHER_SIZE = GGL_DITHER_ORDER * GGL_DITHER_ORDER; +const int GGL_DITHER_MASK = GGL_DITHER_ORDER-1; + +// ---------------------------------------------------------------------------- + +const int GGL_SUBPIXEL_BITS = 4; + +// TRI_FRACTION_BITS defines the number of bits we want to use +// for the sub-pixel coordinates during the edge stepping, the +// value shouldn't be more than 7, or bad things are going to +// happen when drawing large triangles (8 doesn't work because +// 32 bit muls will loose the sign bit) + +#define TRI_FRACTION_BITS (GGL_SUBPIXEL_BITS) +#define TRI_ONE (1 << TRI_FRACTION_BITS) +#define TRI_HALF (1 << (TRI_FRACTION_BITS-1)) +#define TRI_FROM_INT(x) ((x) << TRI_FRACTION_BITS) +#define TRI_FRAC(x) ((x) & (TRI_ONE-1)) +#define TRI_FLOOR(x) ((x) & ~(TRI_ONE-1)) +#define TRI_CEIL(x) (((x) + (TRI_ONE-1)) & ~(TRI_ONE-1)) +#define TRI_ROUND(x) (((x) + TRI_HALF ) & ~(TRI_ONE-1)) + +#define TRI_ROUDNING (1 << (16 - TRI_FRACTION_BITS - 1)) +#define TRI_FROM_FIXED(x) (((x)+TRI_ROUDNING) >> (16-TRI_FRACTION_BITS)) + +#define TRI_SNAP_NEXT_HALF(x) (TRI_CEIL((x)+TRI_HALF) - TRI_HALF) +#define TRI_SNAP_PREV_HALF(x) (TRI_CEIL((x)-TRI_HALF) - TRI_HALF) + +// ---------------------------------------------------------------------------- + +const int GGL_COLOR_BITS = 24; + +// To maintain 8-bits color chanels, with a maximum GGLSurface +// size of 4096 and GGL_SUBPIXEL_BITS=4, we need 8 + 12 + 4 = 24 bits +// for encoding the color iterators + +inline GGLcolor gglFixedToIteratedColor(GGLfixed c) { + return (c << 8) - c; +} + +// ---------------------------------------------------------------------------- + +template<bool> struct CTA; +template<> struct CTA<true> { }; + +#define GGL_CONTEXT(con, c) context_t *con = static_cast<context_t *>(c) +#define GGL_OFFSETOF(field) uintptr_t(&(((context_t*)0)->field)) +#define GGL_INIT_PROC(p, f) p.f = ggl_ ## f; +#define GGL_BETWEEN(x, L, H) (uint32_t((x)-(L)) <= ((H)-(L))) + +#define ggl_likely(x) __builtin_expect(!!(x), 1) +#define ggl_unlikely(x) __builtin_expect(!!(x), 0) + +const int GGL_TEXTURE_UNIT_COUNT = 2; +const int GGL_TMU_STATE = 0x00000001; +const int GGL_CB_STATE = 0x00000002; +const int GGL_PIXEL_PIPELINE_STATE = 0x00000004; + +// ---------------------------------------------------------------------------- + +#define GGL_RESERVE_NEEDS(name, l, s) \ + const uint32_t GGL_NEEDS_##name##_MASK = (((1LU<<(s))-1)<<l); \ + const uint32_t GGL_NEEDS_##name##_SHIFT = (l); + +#define GGL_BUILD_NEEDS(val, name) \ + (((val)<<(GGL_NEEDS_##name##_SHIFT)) & GGL_NEEDS_##name##_MASK) + +#define GGL_READ_NEEDS(name, n) \ + (uint32_t(n & GGL_NEEDS_##name##_MASK) >> GGL_NEEDS_##name##_SHIFT) + +#define GGL_NEED_MASK(name) (uint32_t(GGL_NEEDS_##name##_MASK)) +#define GGL_NEED(name, val) GGL_BUILD_NEEDS(val, name) + +GGL_RESERVE_NEEDS( CB_FORMAT, 0, 6 ) +GGL_RESERVE_NEEDS( SHADE, 6, 1 ) +GGL_RESERVE_NEEDS( W, 7, 1 ) +GGL_RESERVE_NEEDS( BLEND_SRC, 8, 4 ) +GGL_RESERVE_NEEDS( BLEND_DST, 12, 4 ) +GGL_RESERVE_NEEDS( BLEND_SRCA, 16, 4 ) +GGL_RESERVE_NEEDS( BLEND_DSTA, 20, 4 ) +GGL_RESERVE_NEEDS( LOGIC_OP, 24, 4 ) +GGL_RESERVE_NEEDS( MASK_ARGB, 28, 4 ) + +GGL_RESERVE_NEEDS( P_ALPHA_TEST, 0, 3 ) +GGL_RESERVE_NEEDS( P_AA, 3, 1 ) +GGL_RESERVE_NEEDS( P_DEPTH_TEST, 4, 3 ) +GGL_RESERVE_NEEDS( P_MASK_Z, 7, 1 ) +GGL_RESERVE_NEEDS( P_DITHER, 8, 1 ) +GGL_RESERVE_NEEDS( P_FOG, 9, 1 ) +GGL_RESERVE_NEEDS( P_RESERVED1, 10,22 ) + +GGL_RESERVE_NEEDS( T_FORMAT, 0, 6 ) +GGL_RESERVE_NEEDS( T_RESERVED0, 6, 1 ) +GGL_RESERVE_NEEDS( T_POT, 7, 1 ) +GGL_RESERVE_NEEDS( T_S_WRAP, 8, 2 ) +GGL_RESERVE_NEEDS( T_T_WRAP, 10, 2 ) +GGL_RESERVE_NEEDS( T_ENV, 12, 3 ) +GGL_RESERVE_NEEDS( T_LINEAR, 15, 1 ) + +const int GGL_NEEDS_WRAP_CLAMP_TO_EDGE = 0; +const int GGL_NEEDS_WRAP_REPEAT = 1; +const int GGL_NEEDS_WRAP_11 = 2; + +inline uint32_t ggl_wrap_to_needs(uint32_t e) { + switch (e) { + case GGL_CLAMP: return GGL_NEEDS_WRAP_CLAMP_TO_EDGE; + case GGL_REPEAT: return GGL_NEEDS_WRAP_REPEAT; + } + return 0; +} + +inline uint32_t ggl_blendfactor_to_needs(uint32_t b) { + if (b <= 1) return b; + return (b & 0xF)+2; +} + +inline uint32_t ggl_needs_to_blendfactor(uint32_t n) { + if (n <= 1) return n; + return (n - 2) + 0x300; +} + +inline uint32_t ggl_env_to_needs(uint32_t e) { + switch (e) { + case GGL_REPLACE: return 0; + case GGL_MODULATE: return 1; + case GGL_DECAL: return 2; + case GGL_BLEND: return 3; + case GGL_ADD: return 4; + } + return 0; +} + +inline uint32_t ggl_needs_to_env(uint32_t n) { + const uint32_t envs[] = { GGL_REPLACE, GGL_MODULATE, + GGL_DECAL, GGL_BLEND, GGL_ADD }; + return envs[n]; + +} + +// ---------------------------------------------------------------------------- + +enum { + GGL_ENABLE_BLENDING = 0x00000001, + GGL_ENABLE_SMOOTH = 0x00000002, + GGL_ENABLE_AA = 0x00000004, + GGL_ENABLE_LOGIC_OP = 0x00000008, + GGL_ENABLE_ALPHA_TEST = 0x00000010, + GGL_ENABLE_SCISSOR_TEST = 0x00000020, + GGL_ENABLE_TMUS = 0x00000040, + GGL_ENABLE_DEPTH_TEST = 0x00000080, + GGL_ENABLE_STENCIL_TEST = 0x00000100, + GGL_ENABLE_W = 0x00000200, + GGL_ENABLE_DITHER = 0x00000400, + GGL_ENABLE_FOG = 0x00000800, + GGL_ENABLE_POINT_AA_NICE= 0x00001000 +}; + +// ---------------------------------------------------------------------------- + +class needs_filter_t; +struct needs_t { + inline int match(const needs_filter_t& filter); + inline bool operator == (const needs_t& rhs) const { + return (n==rhs.n) && + (p==rhs.p) && + (t[0]==rhs.t[0]) && + (t[1]==rhs.t[1]); + } + inline bool operator != (const needs_t& rhs) const { + return !operator == (rhs); + } + uint32_t n; + uint32_t p; + uint32_t t[GGL_TEXTURE_UNIT_COUNT]; +}; + +inline int compare_type(const needs_t& lhs, const needs_t& rhs) { + return memcmp(&lhs, &rhs, sizeof(needs_t)); +} + +struct needs_filter_t { + needs_t value; + needs_t mask; +}; + +int needs_t::match(const needs_filter_t& filter) { + uint32_t result = + ((filter.value.n ^ n) & filter.mask.n) | + ((filter.value.p ^ p) & filter.mask.p) | + ((filter.value.t[0] ^ t[0]) & filter.mask.t[0]) | + ((filter.value.t[1] ^ t[1]) & filter.mask.t[1]); + return (result == 0); +} + +// ---------------------------------------------------------------------------- + +struct context_t; +class Assembly; + +struct blend_state_t { + uint32_t src; + uint32_t dst; + uint32_t src_alpha; + uint32_t dst_alpha; + uint8_t reserved; + uint8_t alpha_separate; + uint8_t operation; + uint8_t equation; +}; + +struct mask_state_t { + uint8_t color; + uint8_t depth; + uint32_t stencil; +}; + +struct clear_state_t { + GGLclampx r; + GGLclampx g; + GGLclampx b; + GGLclampx a; + GGLclampx depth; + GGLint stencil; + uint32_t colorPacked; + uint32_t depthPacked; + uint32_t stencilPacked; + uint32_t dirty; +}; + +struct fog_state_t { + uint8_t color[4]; +}; + +struct logic_op_state_t { + uint16_t opcode; +}; + +struct alpha_test_state_t { + uint16_t func; + GGLcolor ref; +}; + +struct depth_test_state_t { + uint16_t func; + GGLclampx clearValue; +}; + +struct scissor_t { + uint32_t user_left; + uint32_t user_right; + uint32_t user_top; + uint32_t user_bottom; + uint32_t left; + uint32_t right; + uint32_t top; + uint32_t bottom; +}; + +struct pixel_t { + uint32_t c[4]; + uint8_t s[4]; +}; + +struct surface_t { + union { + GGLSurface s; + // Keep the following struct field types in line with the corresponding + // GGLSurface fields to avoid mismatches leading to errors. + struct { + GGLsizei reserved; + GGLuint width; + GGLuint height; + GGLint stride; + GGLubyte* data; + GGLubyte format; + GGLubyte dirty; + GGLubyte pad[2]; + }; + }; + void (*read) (const surface_t* s, context_t* c, + uint32_t x, uint32_t y, pixel_t* pixel); + void (*write)(const surface_t* s, context_t* c, + uint32_t x, uint32_t y, const pixel_t* pixel); +}; + +// ---------------------------------------------------------------------------- + +struct texture_shade_t { + union { + struct { + int32_t is0; + int32_t idsdx; + int32_t idsdy; + int sscale; + int32_t it0; + int32_t idtdx; + int32_t idtdy; + int tscale; + }; + struct { + int32_t v; + int32_t dx; + int32_t dy; + int scale; + } st[2]; + }; +}; + +struct texture_iterators_t { + // these are not encoded in the same way than in the + // texture_shade_t structure + union { + struct { + GGLfixed ydsdy; + GGLfixed dsdx; + GGLfixed dsdy; + int sscale; + GGLfixed ydtdy; + GGLfixed dtdx; + GGLfixed dtdy; + int tscale; + }; + struct { + GGLfixed ydvdy; + GGLfixed dvdx; + GGLfixed dvdy; + int scale; + } st[2]; + }; +}; + +struct texture_t { + surface_t surface; + texture_iterators_t iterators; + texture_shade_t shade; + uint32_t s_coord; + uint32_t t_coord; + uint16_t s_wrap; + uint16_t t_wrap; + uint16_t min_filter; + uint16_t mag_filter; + uint16_t env; + uint8_t env_color[4]; + uint8_t enable; + uint8_t dirty; +}; + +struct raster_t { + GGLfixed x; + GGLfixed y; +}; + +struct framebuffer_t { + surface_t color; + surface_t read; + surface_t depth; + surface_t stencil; + int16_t *coverage; + size_t coverageBufferSize; +}; + +// ---------------------------------------------------------------------------- + +struct iterators_t { + int32_t xl; + int32_t xr; + int32_t y; + GGLcolor ydady; + GGLcolor ydrdy; + GGLcolor ydgdy; + GGLcolor ydbdy; + GGLfixed ydzdy; + GGLfixed ydwdy; + GGLfixed ydfdy; +}; + +struct shade_t { + GGLcolor a0; + GGLcolor dadx; + GGLcolor dady; + GGLcolor r0; + GGLcolor drdx; + GGLcolor drdy; + GGLcolor g0; + GGLcolor dgdx; + GGLcolor dgdy; + GGLcolor b0; + GGLcolor dbdx; + GGLcolor dbdy; + uint32_t z0; + GGLfixed32 dzdx; + GGLfixed32 dzdy; + GGLfixed w0; + GGLfixed dwdx; + GGLfixed dwdy; + uint32_t f0; + GGLfixed dfdx; + GGLfixed dfdy; +}; + +// these are used in the generated code +// we use this mirror structure to improve +// data locality in the pixel pipeline +struct generated_tex_vars_t { + uint32_t width; + uint32_t height; + uint32_t stride; + uintptr_t data; + int32_t dsdx; + int32_t dtdx; + int32_t spill[2]; +}; + +struct generated_vars_t { + struct { + int32_t c; + int32_t dx; + } argb[4]; + int32_t aref; + int32_t dzdx; + int32_t zbase; + int32_t f; + int32_t dfdx; + int32_t spill[3]; + generated_tex_vars_t texture[GGL_TEXTURE_UNIT_COUNT]; + int32_t rt; + int32_t lb; +}; + +// ---------------------------------------------------------------------------- + +struct state_t { + framebuffer_t buffers; + texture_t texture[GGL_TEXTURE_UNIT_COUNT]; + scissor_t scissor; + raster_t raster; + blend_state_t blend; + alpha_test_state_t alpha_test; + depth_test_state_t depth_test; + mask_state_t mask; + clear_state_t clear; + fog_state_t fog; + logic_op_state_t logic_op; + uint32_t enables; + uint32_t enabled_tmu; + needs_t needs; +}; + +// ---------------------------------------------------------------------------- + +struct context_t { + GGLContext procs; + state_t state; + shade_t shade; + iterators_t iterators; + generated_vars_t generated_vars __attribute__((aligned(32))); + uint8_t ditherMatrix[GGL_DITHER_SIZE] __attribute__((aligned(32))); + uint32_t packed; + uint32_t packed8888; + const GGLFormat* formats; + uint32_t dirty; + texture_t* activeTMU; + uint32_t activeTMUIndex; + + void (*init_y)(context_t* c, int32_t y); + void (*step_y)(context_t* c); + void (*scanline)(context_t* c); + void (*span)(context_t* c); + void (*rect)(context_t* c, size_t yc); + + void* base; + Assembly* scanline_as; + GGLenum error; +}; + +// ---------------------------------------------------------------------------- + +void ggl_init_context(context_t* context); +void ggl_uninit_context(context_t* context); +void ggl_error(context_t* c, GGLenum error); +int64_t ggl_system_time(); + +// ---------------------------------------------------------------------------- + +}; + +#endif // ANDROID_GGL_CONTEXT_H + |