/* * 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) { return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); } inline uint32_t GGL_HOST_TO_RGBA(uint32_t v) { return (v<<24) | (v>>24) | ((v<<8)&0xff0000) | ((v>>8)&0xff00); } #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) int(&(((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; struct { uint32_t reserved; uint32_t width; uint32_t height; int32_t stride; uint8_t* data; uint8_t format; uint8_t dirty; uint8_t 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; int32_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