Ejemplo n.º 1
0
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();
}
Ejemplo n.º 2
0
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);

}
Ejemplo n.º 3
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;
}