Home | History | Annotate | Download | only in libpixelflinger
      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
    172