| The Android Open Source Project | dd7bc33 | 2009-03-03 19:32:55 -0800 | [diff] [blame] | 1 | /* libs/pixelflinger/clear.cpp | 
|  | 2 | ** | 
|  | 3 | ** Copyright 2006, The Android Open Source Project | 
|  | 4 | ** | 
|  | 5 | ** Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 6 | ** you may not use this file except in compliance with the License. | 
|  | 7 | ** You may obtain a copy of the License at | 
|  | 8 | ** | 
|  | 9 | **     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 10 | ** | 
|  | 11 | ** Unless required by applicable law or agreed to in writing, software | 
|  | 12 | ** distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 13 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 14 | ** See the License for the specific language governing permissions and | 
|  | 15 | ** limitations under the License. | 
|  | 16 | */ | 
|  | 17 |  | 
|  | 18 | #include <cutils/memory.h> | 
|  | 19 |  | 
|  | 20 | #include "clear.h" | 
|  | 21 | #include "buffer.h" | 
|  | 22 |  | 
|  | 23 | namespace android { | 
|  | 24 |  | 
|  | 25 | // ---------------------------------------------------------------------------- | 
|  | 26 |  | 
|  | 27 | static void ggl_clear(void* c, GGLbitfield mask); | 
|  | 28 | static void ggl_clearColorx(void* c, | 
|  | 29 | GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a); | 
|  | 30 | static void ggl_clearDepthx(void* c, GGLclampx depth); | 
|  | 31 | static void ggl_clearStencil(void* c, GGLint s); | 
|  | 32 |  | 
|  | 33 | // ---------------------------------------------------------------------------- | 
|  | 34 |  | 
|  | 35 | void ggl_init_clear(context_t* c) | 
|  | 36 | { | 
|  | 37 | GGLContext& procs = *(GGLContext*)c; | 
|  | 38 | GGL_INIT_PROC(procs, clear); | 
|  | 39 | GGL_INIT_PROC(procs, clearColorx); | 
|  | 40 | GGL_INIT_PROC(procs, clearDepthx); | 
|  | 41 | GGL_INIT_PROC(procs, clearStencil); | 
|  | 42 | c->state.clear.dirty =  GGL_STENCIL_BUFFER_BIT | | 
|  | 43 | GGL_COLOR_BUFFER_BIT | | 
|  | 44 | GGL_DEPTH_BUFFER_BIT; | 
|  | 45 | c->state.clear.depth = FIXED_ONE; | 
|  | 46 | } | 
|  | 47 |  | 
|  | 48 | // ---------------------------------------------------------------------------- | 
|  | 49 |  | 
|  | 50 | static void memset2d(context_t* c, const surface_t& s, uint32_t packed, | 
|  | 51 | uint32_t l, uint32_t t, uint32_t w, uint32_t h) | 
|  | 52 | { | 
|  | 53 | const uint32_t size = c->formats[s.format].size; | 
|  | 54 | const int32_t stride = s.stride * size; | 
|  | 55 | uint8_t* dst = (uint8_t*)s.data + (l + t*s.stride)*size; | 
|  | 56 | w *= size; | 
|  | 57 |  | 
|  | 58 | if (ggl_likely(int32_t(w) == stride)) { | 
|  | 59 | // clear the whole thing in one call | 
|  | 60 | w *= h; | 
|  | 61 | h = 1; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | switch (size) { | 
|  | 65 | case 1: | 
|  | 66 | do { | 
|  | 67 | memset(dst, packed, w); | 
|  | 68 | dst += stride; | 
|  | 69 | } while(--h); | 
|  | 70 | break; | 
|  | 71 | case 2: | 
|  | 72 | do { | 
|  | 73 | android_memset16((uint16_t*)dst, packed, w); | 
|  | 74 | dst += stride; | 
|  | 75 | } while(--h); | 
|  | 76 | break; | 
|  | 77 | case 3: // XXX: 24-bit clear. | 
|  | 78 | break; | 
|  | 79 | case 4: | 
|  | 80 | do { | 
|  | 81 | android_memset32((uint32_t*)dst, packed, w); | 
|  | 82 | dst += stride; | 
|  | 83 | } while(--h); | 
|  | 84 | break; | 
|  | 85 | } | 
|  | 86 | } | 
|  | 87 |  | 
|  | 88 | static inline GGLfixed fixedToZ(GGLfixed z) { | 
|  | 89 | return GGLfixed(((int64_t(z) << 16) - z) >> 16); | 
|  | 90 | } | 
|  | 91 |  | 
|  | 92 | static void ggl_clear(void* con, GGLbitfield mask) | 
|  | 93 | { | 
|  | 94 | GGL_CONTEXT(c, con); | 
|  | 95 |  | 
|  | 96 | // XXX: rgba-dithering, rgba-masking | 
|  | 97 | // XXX: handle all formats of Z and S | 
|  | 98 |  | 
|  | 99 | const uint32_t l = c->state.scissor.left; | 
|  | 100 | const uint32_t t = c->state.scissor.top; | 
|  | 101 | uint32_t w = c->state.scissor.right - l; | 
|  | 102 | uint32_t h = c->state.scissor.bottom - t; | 
|  | 103 |  | 
|  | 104 | if (!w || !h) | 
|  | 105 | return; | 
|  | 106 |  | 
|  | 107 | // unexsiting buffers have no effect... | 
|  | 108 | if (c->state.buffers.color.format == 0) | 
|  | 109 | mask &= ~GGL_COLOR_BUFFER_BIT; | 
|  | 110 |  | 
|  | 111 | if (c->state.buffers.depth.format == 0) | 
|  | 112 | mask &= ~GGL_DEPTH_BUFFER_BIT; | 
|  | 113 |  | 
|  | 114 | if (c->state.buffers.stencil.format == 0) | 
|  | 115 | mask &= ~GGL_STENCIL_BUFFER_BIT; | 
|  | 116 |  | 
|  | 117 | if (mask & GGL_COLOR_BUFFER_BIT) { | 
|  | 118 | if (c->state.clear.dirty & GGL_COLOR_BUFFER_BIT) { | 
|  | 119 | c->state.clear.dirty &= ~GGL_COLOR_BUFFER_BIT; | 
|  | 120 |  | 
|  | 121 | uint32_t colorPacked = ggl_pack_color(c, | 
|  | 122 | c->state.buffers.color.format, | 
|  | 123 | gglFixedToIteratedColor(c->state.clear.r), | 
|  | 124 | gglFixedToIteratedColor(c->state.clear.g), | 
|  | 125 | gglFixedToIteratedColor(c->state.clear.b), | 
|  | 126 | gglFixedToIteratedColor(c->state.clear.a)); | 
|  | 127 |  | 
|  | 128 | c->state.clear.colorPacked = GGL_HOST_TO_RGBA(colorPacked); | 
|  | 129 | } | 
|  | 130 | const uint32_t packed = c->state.clear.colorPacked; | 
|  | 131 | memset2d(c, c->state.buffers.color, packed, l, t, w, h); | 
|  | 132 | } | 
|  | 133 | if (mask & GGL_DEPTH_BUFFER_BIT) { | 
|  | 134 | if (c->state.clear.dirty & GGL_DEPTH_BUFFER_BIT) { | 
|  | 135 | c->state.clear.dirty &= ~GGL_DEPTH_BUFFER_BIT; | 
|  | 136 | uint32_t depth = fixedToZ(c->state.clear.depth); | 
|  | 137 | c->state.clear.depthPacked = (depth<<16)|depth; | 
|  | 138 | } | 
|  | 139 | const uint32_t packed = c->state.clear.depthPacked; | 
|  | 140 | memset2d(c, c->state.buffers.depth, packed, l, t, w, h); | 
|  | 141 | } | 
|  | 142 |  | 
|  | 143 | // XXX: do stencil buffer | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | static void ggl_clearColorx(void* con, | 
|  | 147 | GGLclampx r, GGLclampx g, GGLclampx b, GGLclampx a) | 
|  | 148 | { | 
|  | 149 | GGL_CONTEXT(c, con); | 
|  | 150 | c->state.clear.r = gglClampx(r); | 
|  | 151 | c->state.clear.g = gglClampx(g); | 
|  | 152 | c->state.clear.b = gglClampx(b); | 
|  | 153 | c->state.clear.a = gglClampx(a); | 
|  | 154 | c->state.clear.dirty |= GGL_COLOR_BUFFER_BIT; | 
|  | 155 | } | 
|  | 156 |  | 
|  | 157 | static void ggl_clearDepthx(void* con, GGLclampx depth) | 
|  | 158 | { | 
|  | 159 | GGL_CONTEXT(c, con); | 
|  | 160 | c->state.clear.depth = gglClampx(depth); | 
|  | 161 | c->state.clear.dirty |= GGL_DEPTH_BUFFER_BIT; | 
|  | 162 | } | 
|  | 163 |  | 
|  | 164 | static void ggl_clearStencil(void* con, GGLint s) | 
|  | 165 | { | 
|  | 166 | GGL_CONTEXT(c, con); | 
|  | 167 | c->state.clear.stencil = s; | 
|  | 168 | c->state.clear.dirty |= GGL_STENCIL_BUFFER_BIT; | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | }; // namespace android |