void piglit_init(int argc, char **argv) { int prog; int tex_location; int i; enum shader_target test_stage = UNKNOWN; bool sampler_found = false; for (i = 1; i < argc; i++) { if (test_stage == UNKNOWN) { /* Maybe it's the shader stage? */ if (strcmp(argv[i], "vs") == 0) { test_stage = VS; continue; } else if (strcmp(argv[i], "fs") == 0) { test_stage = FS; continue; } } if (strcmp(argv[i], "140") == 0) { shader_version = 140; continue; } /* Maybe it's the sampler type? */ if (!sampler_found && (sampler_found = select_sampler(argv[i]))) continue; fail_and_show_usage(); } if (test_stage == UNKNOWN || !sampler_found) fail_and_show_usage(); /* Not implemented yet */ assert(sampler.target != GL_TEXTURE_CUBE_MAP_ARRAY); require_GL_features(test_stage); prog = generate_GLSL(test_stage); if (!prog) piglit_report_result(PIGLIT_FAIL); tex_location = piglit_GetUniformLocation(prog, "tex"); lod_location = piglit_GetUniformLocation(prog, "lod"); vertex_location = piglit_GetAttribLocation(prog, "vertex"); piglit_UseProgram(prog); piglit_Uniform1i(tex_location, 0); /* Create textures and set miplevel info */ set_base_size(); compute_miplevel_info(); generate_texture(); }
void MainWidget::initTextures() { static const GLint swizzles[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glGenTextures(1, &textureA); glBindTexture(GL_TEXTURE_2D, textureA); glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, WIDTH, HEIGHT); glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzles); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glGenTextures(1, &textureB); glBindTexture(GL_TEXTURE_2D, textureB); glTexStorage2D(GL_TEXTURE_2D, 4, GL_RGBA8, WIDTH, HEIGHT); unsigned char * datain = new unsigned char[WIDTH * HEIGHT]; generate_texture(datain, WIDTH, HEIGHT); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RED, GL_UNSIGNED_BYTE, datain); glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzles); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); }
// WARNING: // This function contains an unusual amount of raw pointers, and is // the most C-like function you can get without being C++. // Sorry Joshua. void Text::render() { int width = this->width; int height = this->height; std::pair<int,int> window_size = window->get_window_size(); // Automatic sizing if dimension is 0. if (width == 0) { switch (alignment_h) { default: case Alignment::LEFT: width = window_size.first - this->x; break; case Alignment::CENTRE: width = ((window_size.first / 2) < this->x) ? this->x : window_size.first - this->x; break; case Alignment::RIGHT: width = this->x; break; } } if (height == 0) { switch (alignment_v) { default: case Alignment::TOP: height = this->y; break; case Alignment::CENTRE: height = ((window_size.second / 2) < this->y) ? window_size.second - this->y : this->y; break; case Alignment::BOTTOM: height = window_size.second - this->y; break; } } // If they are still zero, don't continue. if (width == 0 || height == 0) { throw Text::RenderException("Invalid dimensions after auto-sizing."); } int available_width = width; // It took a whole day to discover that there was a bug in // SDL_ttf. Starting with certain characters on certain // fonts seems to break it. :( // As a hack, prepend and (for balance) append a space. int border; TTF_SizeUTF8(font.font, " ", &border, NULL); border *= 2; // If they are still zero, don't continue. if (available_width <= 0) { throw Text::RenderException("No available width for rendering text."); } int line_height = TTF_FontHeight(font.font); int line_number = 0; int lost_lines = 0; int used_width = 0; int length = (int)text.length(); // Entire text. const char* ctext = text.c_str(); // Line of text. char* line = new char[length+1]; // Null-terminator separated lines of text. // The worst case is a character per line, so we need to do // 2 * length (character, null, character, null, ...). char* lines = new char[2*length+1]; // Pointer to within lines. char* lines_scan = lines; // Text indexing. for (int t = 0; t < length; t++) { int line_width = 0; // Word indexing. int w = 0; // Stores (from the beginning) a word in ctext (copy). line[0] = '\0'; // Points to the end of the last successfully fitting word in // line. int ll = 0; // Line indexing. for (int l = t; l < length; l++) { // Find word end. for (w = l; w < length && (ctext[w] != ' ' && ctext[w] != '\n'); w++) { // As we are dealing with UTF-8, we must make sure to // copy an entire character if it is more than one byte. // The bit formats of UTF-8 characters are: // 0xxxxxxx // 110xxxxx 10xxxxxx // 1110xxxx 10xxxxxx 10xxxxxx // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx // // ... Well, actually it's not THAT simple, because // there are these magical characters which modify other // characters... But it's not worth the effort. if (ctext[l] & 0x80) { // The number of bits in the first byte set to 1 // before the first zero indicate the total number // of bytes to use for the UTF-8 character. for (int bits = ctext[w] << 1; w < length && (bits & 0x80); w++, bits <<= 1); } } // Copy word into line. for (; l < w; l++) { line[l - t] = ctext[l]; } line[l - t] = '\0'; // Test line length. TTF_SizeUTF8(font.font, line, &line_width, NULL); // Part of SDL_ttf bug workaround. line_width+=border; if (line_width <= available_width) { if (line_width > used_width) { used_width = line_width; } // Mark current position as valid. ll = l - t; // If this is the end of a line, or whole text, stop. if (ctext[w] == '\n' || ctext[w] == '\0') { t = l; // Note the string is already null terminated. break; } else { // Replace null terminator with word separator. line[ll] = ctext[w]; } } else { if (ll > 0) { // There are some fittable words. // As the line overflows with the current l, set the // text index to the last fit. t += ll; } else { // There are no separators to break on. // We're going to have to cut a word in half. // Swapped-out character char c; int left = 0; int right = l - t; // Search index within line. int ls; ll = 0; for (ls = (right + left) / 2; ls != ll; ls = (right + left) / 2) { ll = ls; c = line[ls]; line[ls] = 0; TTF_SizeUTF8(font.font, line, &line_width, NULL); // Part of SDL_ttf bug workaround. line_width+=border; if (line_width <= available_width) { if (line_width > used_width) { used_width = line_width; } left = ls; } else { right = ls; } line[ls] = c; } // Don't skip the non-separating character. t += ll - 1; } // Null terminate for rendering. line[ll] = '\0'; break; } } // Copy the line into lines (using lines_scan). int i; for (i = 0; line[i] != '\0'; ++i) { lines_scan[i] = line[i]; } lines_scan[i] = '\0'; lines_scan = &lines_scan[i+1]; ++line_number; if (line[0] == '\0') { // Check that we aren't going to chase our tailes trying to fit an unfittable character. if (ctext[w] != '\n') { LOG(WARNING) << "Cannot render text: character too large."; delete[] line; delete[] lines; throw Text::RenderException("A character is too large"); } else { // It's a blank line. continue; } } } int line_count = line_number; int used_height = line_count * line_height; used_width += border; image = Image(used_width, (used_height < height) ? used_height : height, true); uint8_t clear_colour[4] = {rgba[0], rgba[1], rgba[2], 0x00}; uint8_t clear_mask[4] = {0xff, 0xff, 0xff, 0xff}; image.clear(clear_colour, clear_mask); // image.clear(0xffffff00, 0xffffffff); // Render all lines of text. SDL_Color blank; blank.r = blank.g = blank.b = blank.a = 0; SDL_Color colour; colour.r = rgba[0]; colour.g = rgba[1]; colour.b = rgba[2]; colour.a = rgba[3]; lines_scan = lines; for (int line_number = 0; line_number < line_count; ++line_number) { // Render line VLOG(2) << "Rendering line of text: \"" << lines_scan << "\"."; if (lines_scan[0] == '\0') { // Skip it - it's a new line. lines_scan = &lines_scan[1]; continue; } SDL_Surface* rendered_line; { // It took a whole day to discover that there was a bug in // SDL_ttf. Starting with certain characters on certain // fonts seems to break it. :( // As a hack, prepend and (for balance) append a space. std::stringstream safe; safe << " " << lines_scan << " "; std::string safe_str(safe.str()); if (smooth) { rendered_line = TTF_RenderUTF8_Shaded(font.font, safe_str.c_str(), colour, blank); } else { rendered_line = TTF_RenderUTF8_Solid(font.font, safe_str.c_str(), colour); } } if (rendered_line == nullptr) { LOG(WARNING) << "Cannot render line of text: \"" << lines_scan << "\"."; delete[] line; delete[] lines; throw Text::RenderException("Cannot render line of text"); } #ifdef TEXT_SAFE_SURFACE // This surface has a known format. SDL_Surface* compatible = SDL_CreateRGBSurface(0, // Unsed rendered_line->w, rendered_line->h, 32, 0x00, 0x00, 0x00, 0xff ); SDL_FillRect(compatible, NULL, 0); SDL_SetSurfaceBlendMode(rendered_line, SDL_BLENDMODE_NONE); SDL_BlitSurface(rendered_line, NULL, compatible, NULL); SDL_LockSurface(compatible); // pitch is in bytes, not pixels. RGBA = 4 bytes. int jump = compatible->pitch / 4; #else SDL_LockSurface(rendered_line); int jump = rendered_line->pitch; #endif // "What is this pointless copy?" you might ask. // Well, it is a suggestion to the c++ compiler that smooth // will not change throughout this function, so it can // optimise the if containing _smooth out of the for loop // entirely, rather than checking it every single iteration. int _smooth = smooth; int x_offset; int y_offset; switch (alignment_h) { default: case Alignment::LEFT: x_offset = 0; break; case Alignment::CENTRE: x_offset = (used_width - rendered_line->w) / 2; break; case Alignment::RIGHT: x_offset = used_width - rendered_line->w; break; } switch (alignment_v) { default: case Alignment::TOP: y_offset = line_number * line_height; break; case Alignment::CENTRE: y_offset = line_number * line_height - (used_height - image.height) / 2; break; case Alignment::BOTTOM: y_offset = line_number * line_height - (used_height - image.height); break; } // x surface int xs; // y surface int ys; for (ys = 0; ys < rendered_line->h; ++ys) { int yi = ys + y_offset; if (yi >= image.height) { lost_lines++; break; } else if (yi < 0) { continue; } int begin_xs((x_offset >= 0) ? 0 : -x_offset); int end_xs((rendered_line->w < image.width - x_offset) ? rendered_line->w : image.width - x_offset); for (xs = begin_xs; xs < end_xs; ++xs) { #ifdef TEXT_SAFE_SURFACE image.flipped_pixels[yi][xs + x_offset].a = (((Uint32*)compatible->pixels)[(ys*jump + xs)]); #else if (_smooth) { image.flipped_pixels[yi][xs + x_offset].a = (((Uint8*)rendered_line->pixels)[(ys*jump + xs)]); } else { image.flipped_pixels[yi][xs + x_offset].a = (((Uint8*)rendered_line->pixels)[(ys*jump + xs)]) ? 255 : 0; } #endif } } #ifdef TEXT_SAFE_SURFACE SDL_UnlockSurface(compatible); SDL_FreeSurface(compatible); #else SDL_UnlockSurface(rendered_line); #endif SDL_FreeSurface(rendered_line); if (ys < line_height) { LOG(WARNING) << "Text overflow."; break; } // Set lines_scan to start next line while (lines_scan[0] != '\0') { lines_scan = &lines_scan[1]; } lines_scan = &lines_scan[1]; } this->used_width = used_width; this->used_height = used_height; delete[] line; delete[] lines; generate_texture(); dirty_texture = false; dirty_vbo = true; }