Esempio n. 1
0
static cg_texture_t *
make_texture (void)
{
  void *tex_data;
  uint32_t *p;
  cg_texture_t *tex;
  int partx, party, width, height;

  p = tex_data = c_malloc (TEXTURE_SIZE * TEXTURE_SIZE * 4);

  /* Make a texture with a different color for each part */
  for (party = 0; party < PARTS; party++)
    {
      height = (party < PARTS - 1
                ? PART_SIZE
                : TEXTURE_SIZE - PART_SIZE * (PARTS - 1));

      for (partx = 0; partx < PARTS; partx++)
        {
          uint32_t color = corner_colors[party * PARTS + partx];
          width = (partx < PARTS - 1
                   ? PART_SIZE
                   : TEXTURE_SIZE - PART_SIZE * (PARTS - 1));

          while (width-- > 0)
            *(p++) = C_UINT32_TO_BE (color);
        }

      while (--height > 0)
        {
          memcpy (p, p - TEXTURE_SIZE, TEXTURE_SIZE * 4);
          p += TEXTURE_SIZE;
        }
    }

  tex = test_cg_texture_new_from_data (test_dev,
                                          TEXTURE_SIZE,
                                          TEXTURE_SIZE,
                                          TEST_CG_TEXTURE_NO_ATLAS,
                                          CG_PIXEL_FORMAT_RGBA_8888_PRE,
                                          TEXTURE_SIZE * 4,
                                          tex_data);

  c_free (tex_data);

  if (test_verbose ())
    {
      if (cg_texture_is_sliced (tex))
        c_print ("Texture is sliced\n");
      else
        c_print ("Texture is not sliced\n");
    }

  /* The texture should be sliced unless NPOTs are supported */
  c_assert (cg_has_feature (test_dev, CG_FEATURE_ID_TEXTURE_NPOT)
            ? !cg_texture_is_sliced (tex)
            : cg_texture_is_sliced (tex));

  return tex;
}
Esempio n. 2
0
static int
get_max_activateable_texture_units(cg_device_t *dev)
{
    if (C_UNLIKELY(dev->max_activateable_texture_units == -1)) {
        GLint values[3];
        int n_values = 0;
        int i;

#ifdef CG_HAS_GL_SUPPORT
        if (!_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED)) {
            /* GL_MAX_TEXTURE_COORDS is provided for GLSL. It defines
             * the number of texture coordinates that can be uploaded
             * (but doesn't necessarily relate to how many texture
             *  images can be sampled) */
            if (cg_has_feature(dev, CG_FEATURE_ID_GLSL)) {
                /* Previously this code subtracted the value by one but there
                   was no explanation for why it did this and it doesn't seem
                   to make sense so it has been removed */
                GE(dev,
                   glGetIntegerv(GL_MAX_TEXTURE_COORDS, values + n_values++));

                /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS is defined for GLSL */
                GE(dev,
                   glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
                                 values + n_values++));
            }
        }
#endif /* CG_HAS_GL_SUPPORT */

#ifdef CG_HAS_GLES2_SUPPORT
        if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED)) {
            GE(dev, glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, values + n_values));
            /* Two of the vertex attribs need to be used for the position
               and color */
            values[n_values++] -= 2;

            GE(dev,
               glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
                             values + n_values++));
        }
#endif

        c_assert(n_values <= C_N_ELEMENTS(values) && n_values > 0);

        /* Use the maximum value */
        dev->max_activateable_texture_units = values[0];
        for (i = 1; i < n_values; i++)
            dev->max_activateable_texture_units =
                MAX(values[i], dev->max_activateable_texture_units);
    }

    return dev->max_activateable_texture_units;
}
Esempio n. 3
0
/* OpenGL - unlike GLES - can upload a sub region of pixel data from a larger
 * source buffer */
static void
prep_gl_for_pixels_upload_full(cg_device_t *dev,
                               int pixels_rowstride,
                               int image_height,
                               int pixels_src_x,
                               int pixels_src_y,
                               int pixels_bpp)
{
    GE(dev,
       glPixelStorei(GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp));

    GE(dev, glPixelStorei(GL_UNPACK_SKIP_PIXELS, pixels_src_x));
    GE(dev, glPixelStorei(GL_UNPACK_SKIP_ROWS, pixels_src_y));

    if (cg_has_feature(dev, CG_FEATURE_ID_TEXTURE_3D))
        GE(dev, glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height));

    _cg_texture_gl_prep_alignment_for_pixels_upload(dev, pixels_rowstride);
}
Esempio n. 4
0
bool
_cg_texture_2d_gl_can_create(cg_device_t *dev,
                             int width,
                             int height,
                             cg_pixel_format_t internal_format)
{
    GLenum gl_intformat;
    GLenum gl_format;
    GLenum gl_type;

#if defined(C_PLATFORM_WEB)
    /* XXX: Although webgl has limited supported from NOP textures, this
     * is a hack to help find places to try and convert over to using
     * NPOT textures... */
    if (!(_cg_util_is_pot(width) && _cg_util_is_pot(height))) {
        c_warning("WARNING: NPOT texture: width=%d height=%d", width, height);
        _c_web_console_trace();
    }
#endif

    /* If NPOT textures aren't supported then the size must be a power
       of two */
    if (!cg_has_feature(dev, CG_FEATURE_ID_TEXTURE_NPOT_BASIC) &&
        (!_cg_util_is_pot(width) || !_cg_util_is_pot(height)))
        return false;

    dev->driver_vtable->pixel_format_to_gl(dev, internal_format,
                                           &gl_intformat, &gl_format,
                                           &gl_type);

    /* Check that the driver can create a texture with that size */
    if (!dev->texture_driver->size_supported(dev,
                                             GL_TEXTURE_2D,
                                             gl_intformat,
                                             gl_format,
                                             gl_type,
                                             width,
                                             height))
        return false;

    return true;
}
Esempio n. 5
0
void
test_npot_texture (void)
{
  if (test_verbose ())
    {
      if (cg_has_feature (test_dev, CG_FEATURE_ID_TEXTURE_NPOT))
        c_print ("NPOT textures are supported\n");
      else
        c_print ("NPOT textures are not supported\n");
    }

  cg_framebuffer_orthographic (test_fb,
                                 0, 0,
                                 cg_framebuffer_get_width (test_fb),
                                 cg_framebuffer_get_height (test_fb),
                                 -1,
                                 100);

  paint ();
  validate_result ();

  if (test_verbose ())
    c_print ("OK\n");
}
Esempio n. 6
0
static bool
setup_spans(cg_device_t *dev,
            cg_texture_2d_sliced_t *tex_2ds,
            int width,
            int height,
            int max_waste,
            cg_pixel_format_t internal_format,
            cg_error_t **error)
{
    int max_width;
    int max_height;
    int n_x_slices;
    int n_y_slices;

    int (*slices_for_size)(int, int, int, c_array_t *);

    /* Initialize size of largest slice according to supported features */
    if (cg_has_feature(dev, CG_FEATURE_ID_TEXTURE_NPOT)) {
        max_width = width;
        max_height = height;
        slices_for_size = _cg_rect_slices_for_size;
    } else {
        max_width = _cg_util_next_p2(width);
        max_height = _cg_util_next_p2(height);
        slices_for_size = _cg_pot_slices_for_size;
    }

    /* Negative number means no slicing forced by the user */
    if (max_waste <= -1) {
        cg_span_t span;

        /* Check if size supported else bail out */
        if (!dev->driver_vtable->texture_2d_can_create(dev, max_width, max_height, internal_format)) {
            _cg_set_error(error,
                          CG_TEXTURE_ERROR,
                          CG_TEXTURE_ERROR_SIZE,
                          "Sliced texture size of %d x %d not possible "
                          "with max waste set to -1",
                          width,
                          height);
            return false;
        }

        n_x_slices = 1;
        n_y_slices = 1;

        /* Init span arrays */
        tex_2ds->slice_x_spans =
            c_array_sized_new(false, false, sizeof(cg_span_t), 1);

        tex_2ds->slice_y_spans =
            c_array_sized_new(false, false, sizeof(cg_span_t), 1);

        /* Add a single span for width and height */
        span.start = 0;
        span.size = max_width;
        span.waste = max_width - width;
        c_array_append_val(tex_2ds->slice_x_spans, span);

        span.size = max_height;
        span.waste = max_height - height;
        c_array_append_val(tex_2ds->slice_y_spans, span);
    } else {
        /* Decrease the size of largest slice until supported by GL */
        while (!dev->driver_vtable->texture_2d_can_create(dev, max_width, max_height, internal_format)) {
            /* Alternate between width and height */
            if (max_width > max_height)
                max_width /= 2;
            else
                max_height /= 2;

            if (max_width == 0 || max_height == 0) {
                /* Maybe it would be ok to just c_warn_if_reached() for this
                 * codepath */
                _cg_set_error(error,
                              CG_TEXTURE_ERROR,
                              CG_TEXTURE_ERROR_SIZE,
                              "No suitable slice geometry found");
                free_spans(tex_2ds);
                return false;
            }
        }

        /* Determine the slices required to cover the bitmap area */
        n_x_slices = slices_for_size(width, max_width, max_waste, NULL);

        n_y_slices = slices_for_size(height, max_height, max_waste, NULL);

        /* Init span arrays with reserved size */
        tex_2ds->slice_x_spans =
            c_array_sized_new(false, false, sizeof(cg_span_t), n_x_slices);

        tex_2ds->slice_y_spans =
            c_array_sized_new(false, false, sizeof(cg_span_t), n_y_slices);

        /* Fill span arrays with info */
        slices_for_size(width, max_width, max_waste, tex_2ds->slice_x_spans);

        slices_for_size(height, max_height, max_waste, tex_2ds->slice_y_spans);
    }

    return true;
}
Esempio n. 7
0
void
_cg_glsl_shader_set_source_with_boilerplate(cg_device_t *dev,
                                            GLuint shader_gl_handle,
                                            GLenum shader_gl_type,
                                            GLsizei count_in,
                                            const char **strings_in,
                                            const GLint *lengths_in)
{
    const char *vertex_boilerplate;
    const char *fragment_boilerplate;

    const char **strings = c_alloca(sizeof(char *) * (count_in + 6));
    GLint *lengths = c_alloca(sizeof(GLint) * (count_in + 6));
    char *version_string;
    int count = 0;

    vertex_boilerplate = _CG_VERTEX_SHADER_BOILERPLATE;
    fragment_boilerplate = _CG_FRAGMENT_SHADER_BOILERPLATE;

    version_string =
        c_strdup_printf("#version %i\n\n", dev->glsl_version_to_use);

    strings[count] = version_string;
    lengths[count++] = -1;

    if (_cg_has_private_feature(dev, CG_PRIVATE_FEATURE_GL_EMBEDDED) &&
        cg_has_feature(dev, CG_FEATURE_ID_TEXTURE_3D)) {
        static const char texture_3d_extension[] =
            "#extension GL_OES_texture_3D : enable\n";
        strings[count] = texture_3d_extension;
        lengths[count++] = sizeof(texture_3d_extension) - 1;
    }

    if (shader_gl_type == GL_VERTEX_SHADER) {
        if (dev->glsl_version_to_use < 130) {
            strings[count] = "#define in attribute\n"
                             "#define out varying\n";
            lengths[count++] = -1;
        } else {
            /* To support source compatibility with glsl >= 1.3 which has
             * replaced
             * all of the texture sampler functions with one polymorphic
             * texture()
             * function we use the preprocessor to map the old names onto the
             * new
             * name...
             */
            strings[count] = "#define texture2D texture\n"
                             "#define texture3D texture\n"
                             "#define textureRect texture\n";
            lengths[count++] = -1;
        }

        strings[count] = vertex_boilerplate;
        lengths[count++] = strlen(vertex_boilerplate);
    } else if (shader_gl_type == GL_FRAGMENT_SHADER) {
        if (dev->glsl_version_to_use < 130) {
            strings[count] = "#define in varying\n"
                             "\n"
                             "#define cg_color_out gl_FragColor\n"
                             "#define cg_depth_out gl_FragDepth\n";
            lengths[count++] = -1;
        }

        strings[count] = fragment_boilerplate;
        lengths[count++] = strlen(fragment_boilerplate);

        if (dev->glsl_version_to_use >= 130) {
            /* FIXME: Support cg_depth_out. */
            /* To support source compatibility with glsl >= 1.3 which has
             * replaced
             * all of the texture sampler functions with one polymorphic
             * texture()
             * function we use the preprocessor to map the old names onto the
             * new
             * name...
             */
            strings[count] = "#define texture2D texture\n"
                             "#define texture3D texture\n"
                             "#define textureRect texture\n"
                             "\n"
                             "out vec4 cg_color_out;\n";
            //"out vec4 cg_depth_out\n";
            lengths[count++] = -1;
        }
    }

    memcpy(strings + count, strings_in, sizeof(char *) * count_in);
    if (lengths_in)
        memcpy(lengths + count, lengths_in, sizeof(GLint) * count_in);
    else {
        int i;

        for (i = 0; i < count_in; i++)
            lengths[count + i] = -1; /* null terminated */
    }
    count += count_in;

    if (C_UNLIKELY(CG_DEBUG_ENABLED(CG_DEBUG_SHOW_SOURCE))) {
        c_string_t *buf = c_string_new(NULL);
        int i;

        c_string_append_printf(buf,
                               "%s shader:\n",
                               shader_gl_type == GL_VERTEX_SHADER ? "vertex"
                               : "fragment");
        for (i = 0; i < count; i++)
            if (lengths[i] != -1)
                c_string_append_len(buf, strings[i], lengths[i]);
            else
                c_string_append(buf, strings[i]);

        c_message("%s", buf->str);

        c_string_free(buf, true);
    }

    GE(dev,
       glShaderSource(
           shader_gl_handle, count, (const char **)strings, lengths));

    c_free(version_string);
}