1edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project/* libs/opengles/mipmap.cpp 2edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** 3edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** Copyright 2006, The Android Open Source Project 4edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** 5edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 6edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** you may not use this file except in compliance with the License. 7edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** You may obtain a copy of the License at 8edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** 9edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 10edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** 11edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 12edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 13edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** See the License for the specific language governing permissions and 15edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project** limitations under the License. 16edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project*/ 17edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 18edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdio.h> 19edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include <stdlib.h> 20edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 21edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "context.h" 22edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "state.h" 23edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "texture.h" 24edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project#include "TextureObjectManager.h" 25edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 26edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectnamespace android { 27edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 28edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project// ---------------------------------------------------------------------------- 29edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 30edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Projectstatus_t buildAPyramid(ogles_context_t* c, EGLTextureObject* tex) 31edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project{ 32edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int level = 0; 33edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const GGLSurface* base = &tex->surface; 34edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const GGLFormat& pixelFormat(c->rasterizer.formats[base->format]); 35edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 36edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int w = base->width; 37edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int h = base->height; 38edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if ((w&h) == 1) 39edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_ERROR; 40edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 41edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project w = (w>>1) ? : 1; 42edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project h = (h>>1) ? : 1; 43edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 44edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project while(true) { 45edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project ++level; 46edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const int bpr = w * pixelFormat.size; 47edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (tex->reallocate(level, w, h, w, 48edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project base->format, base->compressedFormat, bpr) != NO_ERROR) { 49edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_MEMORY; 50edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 51edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 52edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int stride = w; 53edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int bs = base->stride; 54edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project GGLSurface& cur = tex->editMip(level); 55edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 56edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if (base->format == GGL_PIXEL_FORMAT_RGB_565) 57edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project { 58edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t const * src = (uint16_t const *)base->data; 59edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t* dst = (uint16_t*)cur.data; 60edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project const uint32_t mask = 0x07E0F81F; 61edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int y=0 ; y<h ; y++) { 62edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t offset = (y*2) * bs; 63edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int x=0 ; x<w ; x++) { 64edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p00 = src[offset]; 65edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p10 = src[offset+1]; 66edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p01 = src[offset+bs]; 67edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p11 = src[offset+bs+1]; 68edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p00 = (p00 | (p00 << 16)) & mask; 69edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p01 = (p01 | (p01 << 16)) & mask; 70edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p10 = (p10 | (p10 << 16)) & mask; 71edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p11 = (p11 | (p11 << 16)) & mask; 72edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t grb = ((p00 + p10 + p01 + p11) >> 2) & mask; 73edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rgb = (grb & 0xFFFF) | (grb >> 16); 74edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dst[x + y*stride] = rgb; 75edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project offset += 2; 76edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 77edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 78edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 79edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project else if (base->format == GGL_PIXEL_FORMAT_RGBA_5551) 80edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project { 81edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t const * src = (uint16_t const *)base->data; 82edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t* dst = (uint16_t*)cur.data; 83edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int y=0 ; y<h ; y++) { 84edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t offset = (y*2) * bs; 85edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int x=0 ; x<w ; x++) { 86edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p00 = src[offset]; 87edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p10 = src[offset+1]; 88edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p01 = src[offset+bs]; 89edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p11 = src[offset+bs+1]; 90edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t r = ((p00>>11)+(p10>>11)+(p01>>11)+(p11>>11)+2)>>2; 91edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t g = (((p00>>6)+(p10>>6)+(p01>>6)+(p11>>6)+2)>>2)&0x3F; 92edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t b = ((p00&0x3E)+(p10&0x3E)+(p01&0x3E)+(p11&0x3E)+4)>>3; 93edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t a = ((p00&1)+(p10&1)+(p01&1)+(p11&1)+2)>>2; 94edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dst[x + y*stride] = (r<<11)|(g<<6)|(b<<1)|a; 95edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project offset += 2; 96edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 97edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 98edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 99edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project else if (base->format == GGL_PIXEL_FORMAT_RGBA_8888) 100edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project { 101edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t const * src = (uint32_t const *)base->data; 102edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t* dst = (uint32_t*)cur.data; 103edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int y=0 ; y<h ; y++) { 104edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t offset = (y*2) * bs; 105edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int x=0 ; x<w ; x++) { 106edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p00 = src[offset]; 107edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p10 = src[offset+1]; 108edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p01 = src[offset+bs]; 109edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p11 = src[offset+bs+1]; 110edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rb00 = p00 & 0x00FF00FF; 111edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rb01 = p01 & 0x00FF00FF; 112edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rb10 = p10 & 0x00FF00FF; 113edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rb11 = p11 & 0x00FF00FF; 114edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t ga00 = (p00 >> 8) & 0x00FF00FF; 115edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t ga01 = (p01 >> 8) & 0x00FF00FF; 116edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t ga10 = (p10 >> 8) & 0x00FF00FF; 117edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t ga11 = (p11 >> 8) & 0x00FF00FF; 118edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rb = (rb00 + rb01 + rb10 + rb11)>>2; 119edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t ga = (ga00 + ga01 + ga10 + ga11)>>2; 120edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rgba = (rb & 0x00FF00FF) | ((ga & 0x00FF00FF)<<8); 121edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dst[x + y*stride] = rgba; 122edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project offset += 2; 123edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 124edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 125edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 126edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project else if ((base->format == GGL_PIXEL_FORMAT_RGB_888) || 127edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project (base->format == GGL_PIXEL_FORMAT_LA_88) || 128edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project (base->format == GGL_PIXEL_FORMAT_A_8) || 129edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project (base->format == GGL_PIXEL_FORMAT_L_8)) 130edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project { 131edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project int skip; 132edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project switch (base->format) { 133edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project case GGL_PIXEL_FORMAT_RGB_888: skip = 3; break; 134edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project case GGL_PIXEL_FORMAT_LA_88: skip = 2; break; 135edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project default: skip = 1; break; 136edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 137edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint8_t const * src = (uint8_t const *)base->data; 138edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint8_t* dst = (uint8_t*)cur.data; 139edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project bs *= skip; 140edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project stride *= skip; 141edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int y=0 ; y<h ; y++) { 142edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t offset = (y*2) * bs; 143edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int x=0 ; x<w ; x++) { 144edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int c=0 ; c<skip ; c++) { 145edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p00 = src[c+offset]; 146edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p10 = src[c+offset+skip]; 147edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p01 = src[c+offset+bs]; 148edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p11 = src[c+offset+bs+skip]; 149edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dst[x + y*stride + c] = (p00 + p10 + p01 + p11) >> 2; 150edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 151edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project offset += 2*skip; 152edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 153edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 154edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 155edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project else if (base->format == GGL_PIXEL_FORMAT_RGBA_4444) 156edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project { 157edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t const * src = (uint16_t const *)base->data; 158edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint16_t* dst = (uint16_t*)cur.data; 159edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int y=0 ; y<h ; y++) { 160edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project size_t offset = (y*2) * bs; 161edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project for (int x=0 ; x<w ; x++) { 162edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p00 = src[offset]; 163edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p10 = src[offset+1]; 164edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p01 = src[offset+bs]; 165edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t p11 = src[offset+bs+1]; 166edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p00 = ((p00 << 12) & 0x0F0F0000) | (p00 & 0x0F0F); 167edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p10 = ((p10 << 12) & 0x0F0F0000) | (p10 & 0x0F0F); 168edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p01 = ((p01 << 12) & 0x0F0F0000) | (p01 & 0x0F0F); 169edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project p11 = ((p11 << 12) & 0x0F0F0000) | (p11 & 0x0F0F); 170edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rbga = (p00 + p10 + p01 + p11) >> 2; 171edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project uint32_t rgba = (rbga & 0x0F0F) | ((rbga>>12) & 0xF0F0); 172edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project dst[x + y*stride] = rgba; 173edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project offset += 2; 174edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 175edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 176edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } else { 177e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block ALOGE("Unsupported format (%d)", base->format); 178edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return BAD_TYPE; 179edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 180edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 181edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project // exit condition: we just processed the 1x1 LODs 182edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project if ((w&h) == 1) 183edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project break; 184edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 185edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project base = &cur; 186edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project w = (w>>1) ? : 1; 187edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project h = (h>>1) ? : 1; 188edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project } 189edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project return NO_ERROR; 190edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project} 191edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project 192edbf3b6af777b721cd2a1ef461947e51e88241e1The Android Open Source Project}; // namespace android 193