citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

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 }