gl_atlas.cc (2886B)
1 /* 2 * Copyright 2012 Google, Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * Google Author(s): Behdad Esfahbod 17 */ 18 19 #include <err.h> 20 21 #include "gl_atlas.h" // citrun::gl_atlas 22 23 #define gl(name) \ 24 for (GLint __ee, __ii = 0; \ 25 __ii < 1; \ 26 (__ii++, \ 27 (__ee = glGetError()) && \ 28 (fprintf (stderr, "gl" #name " failed with error %04X on line %d\n", __ee, __LINE__), abort (), 0))) \ 29 gl##name 30 31 32 citrun::gl_atlas::gl_atlas(unsigned int w, unsigned int h, 33 unsigned int _item_w, unsigned int item_h_quantum) : 34 tex_w(w), 35 tex_h(h), 36 item_w(_item_w), 37 item_h_q(item_h_quantum), 38 cursor_x(0), 39 cursor_y(0) 40 { 41 TRACE(); 42 43 glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &tex_unit); 44 glGenTextures(1, &tex_name); 45 46 bind_texture(); 47 48 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 49 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 50 51 gl(TexImage2D) (GL_TEXTURE_2D, 0, GL_RGBA, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 52 } 53 54 citrun::gl_atlas::~gl_atlas() 55 { 56 glDeleteTextures(1, &tex_name); 57 } 58 59 void 60 citrun::gl_atlas::bind_texture() 61 { 62 glActiveTexture(tex_unit); 63 glBindTexture(GL_TEXTURE_2D, tex_name); 64 } 65 66 void 67 citrun::gl_atlas::set_uniforms() 68 { 69 GLuint program; 70 glGetIntegerv (GL_CURRENT_PROGRAM, (GLint *) &program); 71 72 glUniform4i(glGetUniformLocation(program, "u_atlas_info"), 73 tex_w, tex_h, item_w, item_h_q); 74 glUniform1i(glGetUniformLocation(program, "u_atlas_tex"), tex_unit - GL_TEXTURE0); 75 } 76 77 void 78 citrun::gl_atlas::alloc(glyphy_rgba_t *data, unsigned int len, 79 unsigned int *px, unsigned int *py) 80 { 81 GLuint w, h, x, y; 82 83 w = item_w; 84 h = (len + w - 1) / w; 85 86 if (cursor_y + h > tex_h) { 87 /* Go to next column */ 88 cursor_x += item_w; 89 cursor_y = 0; 90 } 91 92 if (cursor_x + w <= tex_w && cursor_y + h <= tex_h) 93 { 94 x = cursor_x; 95 y = cursor_y; 96 cursor_y += (h + item_h_q - 1) & ~(item_h_q - 1); 97 } else 98 errx(1, "Ran out of atlas memory"); 99 100 bind_texture(); 101 if (w * h == len) 102 gl(TexSubImage2D) (GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, data); 103 else { 104 gl(TexSubImage2D) (GL_TEXTURE_2D, 0, x, y, w, h - 1, GL_RGBA, GL_UNSIGNED_BYTE, data); 105 /* Upload the last row separately */ 106 gl(TexSubImage2D) (GL_TEXTURE_2D, 0, x, y + h - 1, len - (w * (h - 1)), 1, GL_RGBA, GL_UNSIGNED_BYTE, 107 data + w * (h - 1)); 108 } 109 110 *px = x / item_w; 111 *py = y / item_h_q; 112 }