| /* |
| * 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_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_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) /* NOLINT */ |
| #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 |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| struct 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 |
| |