summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp947
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.h46
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp5
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h4
-rw-r--r--drivers/gles2/shader_gles2.cpp14
-rw-r--r--drivers/gles2/shader_gles2.h1
-rw-r--r--drivers/gles2/shaders/canvas.glsl33
7 files changed, 454 insertions, 596 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index f7b49c627d..d6fbf04353 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -64,13 +64,9 @@ void RasterizerCanvasGLES2::_set_uniforms() {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_PIXEL_SIZE, screen_pixel_size);
}
-
- state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, state.uniforms.texpixel_size);
}
void RasterizerCanvasGLES2::canvas_begin() {
- data.primitive = GL_TRIANGLES;
- data.texture = GL_NONE;
state.canvas_shader.bind();
if (storage->frame.current_rt) {
@@ -99,7 +95,6 @@ void RasterizerCanvasGLES2::canvas_begin() {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- data.texture = storage->resources.white_tex;
glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
glDisableVertexAttribArray(VS::ARRAY_COLOR);
@@ -130,7 +125,7 @@ void RasterizerCanvasGLES2::canvas_begin() {
state.uniforms.extra_matrix = Transform2D();
_set_uniforms();
- state.prev_uniforms = state.uniforms;
+ _bind_quad_buffer();
}
void RasterizerCanvasGLES2::canvas_end() {
@@ -148,7 +143,6 @@ void RasterizerCanvasGLES2::canvas_end() {
RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) {
RasterizerStorageGLES2::Texture *tex_return = NULL;
- GLuint newtexid;
if (p_texture.is_valid()) {
@@ -158,7 +152,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
state.current_tex = RID();
state.current_tex_ptr = NULL;
- newtexid = storage->resources.white_tex;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
} else {
@@ -172,7 +167,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
texture->render_target->used_in_frame = true;
}
- newtexid = texture->tex_id;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
state.current_tex = p_texture;
state.current_tex_ptr = texture;
@@ -183,15 +179,8 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con
state.current_tex = RID();
state.current_tex_ptr = NULL;
- newtexid = storage->resources.white_tex;
- }
-
- if (data.texture != newtexid) {
- _flush();
-
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, newtexid);
- data.texture = newtexid;
+ glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
}
return tex_return;
@@ -201,154 +190,217 @@ void RasterizerCanvasGLES2::_set_texture_rect_mode(bool p_enable, bool p_ninepat
}
void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
- bool single;
- Color color;
+ uint32_t buffer_ofs = 0;
+
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
if (p_singlecolor) {
- single = true;
- color = *p_colors;
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ Color m = *p_colors;
+ glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
} else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+ } else {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Color) * p_vertex_count;
+ }
+
+ if (p_uvs) {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
} else {
- single = false;
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
}
- const bool use_single_color = single;
- const Color single_color = color;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
+
+ glDrawElements(GL_TRIANGLES, p_index_count, GL_UNSIGNED_INT, 0);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}
- for (int i = 0; i < p_vertex_count; ++i) {
- v->v = p_vertices[i];
+void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
- if (p_uvs)
- v->uv = p_uvs[i];
- else
- v->uv = Vector2();
+ uint32_t buffer_ofs = 0;
- ++v;
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), (uint8_t *)0);
+ buffer_ofs += sizeof(Vector2) * p_vertex_count;
+
+ if (p_singlecolor) {
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ Color m = *p_colors;
+ glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a);
+ } else if (!p_colors) {
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
+ } else {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors);
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), ((uint8_t *)0) + buffer_ofs);
+ buffer_ofs += sizeof(Color) * p_vertex_count;
}
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, p_indices, p_index_count * sizeof(int));
+ if (p_uvs) {
+ glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), ((uint8_t *)0) + buffer_ofs);
+ } else {
+ glDisableVertexAttribArray(VS::ARRAY_TEX_UV);
+ }
- _commit(p_vertex_count, p_index_count);
+ glDrawArrays(p_primitive, 0, p_vertex_count);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
}
-void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) {
+void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs) {
- int command_count = p_item->commands.size();
- Item::Command **commands = p_item->commands.ptrw();
+ static const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };
- for (int i = 0; i < command_count; i++) {
+ int color_offset = 0;
+ int uv_offset = 0;
+ int stride = 2;
- Item::Command *command = commands[i];
+ if (p_colors) {
+ color_offset = stride;
+ stride += 4;
+ }
- if (command->type != Item::Command::TYPE_RECT && state.tiled) {
- _flush();
- _untile();
- }
+ if (p_uvs) {
+ uv_offset = stride;
+ stride += 2;
+ }
- switch (command->type) {
+ float buffer_data[(2 + 2 + 4) * 4];
- case Item::Command::TYPE_LINE: {
- const Item::CommandLine *line = static_cast<Item::CommandLine *>(command);
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + 0] = p_vertices[i].x;
+ buffer_data[stride * i + 1] = p_vertices[i].y;
+ }
- if (line->width <= 1) {
- const int p_vertex_count = 2;
- const int p_index_count = 2;
+ if (p_colors) {
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + color_offset + 0] = p_colors[i].r;
+ buffer_data[stride * i + color_offset + 1] = p_colors[i].g;
+ buffer_data[stride * i + color_offset + 2] = p_colors[i].b;
+ buffer_data[stride * i + color_offset + 3] = p_colors[i].a;
+ }
+ }
- _begin(GL_LINES);
- _prepare(p_vertex_count, p_index_count);
+ if (p_uvs) {
+ for (int i = 0; i < p_points; i++) {
+ buffer_data[stride * i + uv_offset + 0] = p_uvs[i].x;
+ buffer_data[stride * i + uv_offset + 1] = p_uvs[i].y;
+ }
+ }
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), buffer_data);
- Vertex vertices[p_vertex_count];
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL);
- vertices[0].v = Vector2(line->from.x, line->from.y);
- vertices[0].c = line->color;
- vertices[0].uv = Vector2();
+ if (p_colors) {
+ glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + color_offset * sizeof(float));
+ glEnableVertexAttribArray(VS::ARRAY_COLOR);
+ }
- vertices[1].v = Vector2(line->to.x, line->to.y);
- vertices[1].c = line->color;
- vertices[1].uv = Vector2();
+ if (p_uvs) {
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), (uint8_t *)0 + uv_offset * sizeof(float));
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
+ }
- memcpy(data.mem_vertex_buffer + data.mem_vertex_buffer_offset, vertices, sizeof(vertices));
+ glDrawArrays(prim[p_points], 0, p_points);
- const int indices[p_index_count] = { 0, 1 };
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material) {
- _commit(p_vertex_count, p_index_count);
- } else {
- const int p_vertex_count = 4;
- const int p_index_count = 6;
+ int command_count = p_item->commands.size();
+ Item::Command **commands = p_item->commands.ptrw();
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
+ for (int i = 0; i < command_count; i++) {
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ Item::Command *command = commands[i];
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ switch (command->type) {
- Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5;
+ case Item::Command::TYPE_LINE: {
- v[0].v = line->from - t;
- v[0].c = line->color;
- v[0].uv = Vector2();
+ Item::CommandLine *line = static_cast<Item::CommandLine *>(command);
- v[1].v = line->from + t;
- v[1].c = line->color;
- v[1].uv = Vector2();
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- v[2].v = line->to + t;
- v[2].c = line->color;
- v[2].uv = Vector2();
+ _bind_canvas_texture(RID(), RID());
+
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, line->color.components);
- v[3].v = line->to - t;
- v[3].c = line->color;
- v[3].uv = Vector2();
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix);
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
+ if (line->width <= 1) {
+ Vector2 verts[2] = {
+ Vector2(line->from.x, line->from.y),
+ Vector2(line->to.x, line->to.y)
};
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+ _draw_gui_primitive(2, verts, NULL, NULL);
+ } else {
+ Vector2 t = (line->from - line->to).normalized().tangent() * line->width * 0.5;
- _commit(p_vertex_count, p_index_count);
- }
+ Vector2 verts[4] = {
+ line->from - t,
+ line->from + t,
+ line->to + t,
+ line->to - t
+ };
+ _draw_gui_primitive(4, verts, NULL, NULL);
+ }
} break;
case Item::Command::TYPE_RECT: {
- const int p_vertex_count = 4;
- const int p_index_count = 6;
-
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
Item::CommandRect *r = static_cast<Item::CommandRect *>(command);
- _bind_shader(p_material);
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, r->modulate.components);
- Rect2 src_rect;
- Rect2 dst_rect;
+ _bind_quad_buffer();
+
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(r->texture, r->normal_map);
if (!tex) {
- dst_rect = Rect2(r->rect.position, r->rect.size);
+ Rect2 dst_rect = Rect2(r->rect.position, r->rect.size);
if (dst_rect.size.width < 0) {
dst_rect.position.x += dst_rect.size.width;
@@ -359,28 +411,24 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
dst_rect.size.height *= -1;
}
- src_rect = Rect2(0, 0, 1, 1);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(0, 0, 1, 1));
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
} else {
- const bool tiled = r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT);
+ bool untile = false;
- if (tiled != state.tiled) {
- _flush();
-
- if (tiled) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- state.tiled = true;
- } else {
- _untile();
- }
+ if (r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT)) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ untile = true;
}
Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height);
+ Rect2 src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
- src_rect = (r->flags & CANVAS_RECT_REGION) ? Rect2(r->source.position * texpixel_size, r->source.size * texpixel_size) : Rect2(0, 0, 1, 1);
- dst_rect = Rect2(r->rect.position, r->rect.size);
+ Rect2 dst_rect = Rect2(r->rect.position, r->rect.size);
if (dst_rect.size.width < 0) {
dst_rect.position.x += dst_rect.size.width;
@@ -393,61 +441,48 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
if (r->flags & CANVAS_RECT_FLIP_H) {
src_rect.size.x *= -1;
- src_rect.position.x -= src_rect.size.width;
}
+
if (r->flags & CANVAS_RECT_FLIP_V) {
src_rect.size.y *= -1;
- src_rect.position.y -= src_rect.size.height;
}
+
if (r->flags & CANVAS_RECT_TRANSPOSE) {
dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
}
- state.uniforms.texpixel_size = texpixel_size;
- }
-
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
-
- // 0,0
- v[0].v = dst_rect.position;
- v[0].c = r->modulate;
- v[0].uv = src_rect.position;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
- // 0,1
- v[1].v = Vector2(dst_rect.position.x, dst_rect.position.y + dst_rect.size.y);
- v[1].c = r->modulate;
- v[1].uv = Vector2(src_rect.position.x, src_rect.position.y + src_rect.size.y);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(dst_rect.position.x, dst_rect.position.y, dst_rect.size.x, dst_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(src_rect.position.x, src_rect.position.y, src_rect.size.x, src_rect.size.y));
- // 1,1
- v[2].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y + dst_rect.size.y);
- v[2].c = r->modulate;
- v[2].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y + src_rect.size.y);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- // 1,0
- v[3].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y);
- v[3].c = r->modulate;
- v[3].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y);
-
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
- };
+ if (untile) {
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ }
+ }
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(int) * p_index_count);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- _commit(p_vertex_count, p_index_count);
} break;
case Item::Command::TYPE_NINEPATCH: {
- const int p_vertex_count = 16;
- const int p_index_count = 54;
-
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
Item::CommandNinePatch *np = static_cast<Item::CommandNinePatch *>(command);
- _bind_shader(p_material);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
+
+ glDisableVertexAttribArray(VS::ARRAY_COLOR);
+ glVertexAttrib4fv(VS::ARRAY_COLOR, np->color.components);
+
RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, np->normal_map);
if (!tex) {
@@ -457,7 +492,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
Size2 texpixel_size(1.0 / tex->width, 1.0 / tex->height);
- state.uniforms.texpixel_size = texpixel_size;
+ // state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
Rect2 source = np->source;
if (source.size.x == 0 && source.size.y == 0) {
@@ -469,334 +505,255 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur
// this buffer contains [ POS POS UV UV ] *
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ float buffer[16 * 2 + 16 * 2];
- v[0].v = np->rect.position;
- v[0].c = np->color;
- v[0].uv = source.position * texpixel_size;
+ {
- v[1].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], 0);
- v[1].c = np->color;
- v[1].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], 0)) * texpixel_size;
+ // first row
- v[2].v = np->rect.position + Vector2(np->rect.size.x - np->margin[MARGIN_RIGHT], 0);
- v[2].c = np->color;
- v[2].uv = (source.position + Vector2(source.size.x - np->margin[MARGIN_RIGHT], 0)) * texpixel_size;
+ buffer[(0 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(0 * 4 * 4) + 1] = np->rect.position.y;
- v[3].v = np->rect.position + Vector2(np->rect.size.x, 0);
- v[3].c = np->color;
- v[3].uv = (source.position + Vector2(source.size.x, 0)) * texpixel_size;
+ buffer[(0 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 3] = source.position.y * texpixel_size.y;
- v[4].v = np->rect.position + Vector2(0, np->margin[MARGIN_TOP]);
- v[4].c = np->color;
- v[4].uv = (source.position + Vector2(0, np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(0 * 4 * 4) + 5] = np->rect.position.y;
- v[5].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP]);
- v[5].c = np->color;
- v[5].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 7] = source.position.y * texpixel_size.y;
- v[6].v = np->rect.position + Vector2(np->rect.size.x - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP]);
- v[6].c = np->color;
- v[6].uv = (source.position + Vector2(source.size.x - np->margin[MARGIN_RIGHT], np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(0 * 4 * 4) + 9] = np->rect.position.y;
- v[7].v = np->rect.position + Vector2(np->rect.size.x, np->margin[MARGIN_TOP]);
- v[7].c = np->color;
- v[7].uv = (source.position + Vector2(source.size.x, np->margin[MARGIN_TOP])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 11] = source.position.y * texpixel_size.y;
- v[8].v = np->rect.position + Vector2(0, np->rect.size.y - np->margin[MARGIN_BOTTOM]);
- v[8].c = np->color;
- v[8].uv = (source.position + Vector2(0, source.size.y - np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(0 * 4 * 4) + 13] = np->rect.position.y;
- v[9].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->rect.size.y - np->margin[MARGIN_BOTTOM]);
- v[9].c = np->color;
- v[9].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], source.size.y - np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(0 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(0 * 4 * 4) + 15] = source.position.y * texpixel_size.y;
- v[10].v = np->rect.position + np->rect.size - Vector2(np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM]);
- v[10].c = np->color;
- v[10].uv = (source.position + source.size - Vector2(np->margin[MARGIN_RIGHT], np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ // second row
- v[11].v = np->rect.position + np->rect.size - Vector2(0, np->margin[MARGIN_BOTTOM]);
- v[11].c = np->color;
- v[11].uv = (source.position + source.size - Vector2(0, np->margin[MARGIN_BOTTOM])) * texpixel_size;
+ buffer[(1 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(1 * 4 * 4) + 1] = np->rect.position.y + np->margin[MARGIN_TOP];
- v[12].v = np->rect.position + Vector2(0, np->rect.size.y);
- v[12].c = np->color;
- v[12].uv = (source.position + Vector2(0, source.size.y)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 3] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- v[13].v = np->rect.position + Vector2(np->margin[MARGIN_LEFT], np->rect.size.y);
- v[13].c = np->color;
- v[13].uv = (source.position + Vector2(np->margin[MARGIN_LEFT], source.size.y)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(1 * 4 * 4) + 5] = np->rect.position.y + np->margin[MARGIN_TOP];
- v[14].v = np->rect.position + np->rect.size - Vector2(np->margin[MARGIN_RIGHT], 0);
- v[14].c = np->color;
- v[14].uv = (source.position + source.size - Vector2(np->margin[MARGIN_RIGHT], 0)) * texpixel_size;
+ buffer[(1 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 7] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- v[15].v = np->rect.position + np->rect.size;
- v[15].c = np->color;
- v[15].uv = (source.position + source.size) * texpixel_size;
+ buffer[(1 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(1 * 4 * 4) + 9] = np->rect.position.y + np->margin[MARGIN_TOP];
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, data.ninepatch_elements, sizeof(data.ninepatch_elements));
+ buffer[(1 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 11] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- _commit(p_vertex_count, p_index_count - (np->draw_center ? 0 : 6));
- } break;
+ buffer[(1 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(1 * 4 * 4) + 13] = np->rect.position.y + np->margin[MARGIN_TOP];
- case Item::Command::TYPE_CIRCLE: {
- Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command);
+ buffer[(1 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(1 * 4 * 4) + 15] = (source.position.y + np->margin[MARGIN_TOP]) * texpixel_size.y;
- _bind_shader(p_material);
+ // thrid row
- const int num_points = 32;
+ buffer[(2 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(2 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- Vector2 points[num_points + 1];
- points[num_points] = circle->pos;
+ buffer[(2 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 3] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- int indices[num_points * 3];
+ buffer[(2 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(2 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- for (int i = 0; i < num_points; i++) {
- points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / num_points), Math::cos(i * Math_PI * 2.0 / num_points)) * circle->radius;
- indices[i * 3 + 0] = i;
- indices[i * 3 + 1] = (i + 1) % num_points;
- indices[i * 3 + 2] = num_points;
- }
+ buffer[(2 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 7] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- _bind_canvas_texture(RID(), RID());
-
- _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true);
- } break;
+ buffer[(2 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(2 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- case Item::Command::TYPE_POLYGON: {
- Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command);
+ buffer[(2 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 11] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- const int *indices = polygon->indices.ptr();
- if (!indices) // self-intersecting polygon
- break;
+ buffer[(2 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(2 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y - np->margin[MARGIN_BOTTOM];
- _bind_shader(p_material);
- RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
+ buffer[(2 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(2 * 4 * 4) + 15] = (source.position.y + source.size.y - np->margin[MARGIN_BOTTOM]) * texpixel_size.y;
- if (texture) {
- Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.uniforms.texpixel_size = texpixel_size;
- }
-
- _draw_polygon(indices, polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
- } break;
-
- case Item::Command::TYPE_POLYLINE: {
- Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command);
+ // fourth row
- if (pline->triangles.size()) {
- const int p_vertex_count = pline->triangles.size();
- const int p_triangle_count = p_vertex_count - 2;
- const int p_index_count = p_triangle_count * 3;
+ buffer[(3 * 4 * 4) + 0] = np->rect.position.x;
+ buffer[(3 * 4 * 4) + 1] = np->rect.position.y + np->rect.size.y;
- _begin(GL_TRIANGLES);
- _prepare(p_vertex_count, p_index_count);
+ buffer[(3 * 4 * 4) + 2] = source.position.x * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 3] = (source.position.y + source.size.y) * texpixel_size.y;
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ buffer[(3 * 4 * 4) + 4] = np->rect.position.x + np->margin[MARGIN_LEFT];
+ buffer[(3 * 4 * 4) + 5] = np->rect.position.y + np->rect.size.y;
- const Vector2 *t = pline->triangles.ptr();
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ buffer[(3 * 4 * 4) + 6] = (source.position.x + np->margin[MARGIN_LEFT]) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 7] = (source.position.y + source.size.y) * texpixel_size.y;
- const bool p_singlecolor = pline->triangle_colors.size() == 1;
- const Color *p_colors = pline->triangle_colors.ptr();
+ buffer[(3 * 4 * 4) + 8] = np->rect.position.x + np->rect.size.x - np->margin[MARGIN_RIGHT];
+ buffer[(3 * 4 * 4) + 9] = np->rect.position.y + np->rect.size.y;
- bool single;
- Color color;
+ buffer[(3 * 4 * 4) + 10] = (source.position.x + source.size.x - np->margin[MARGIN_RIGHT]) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 11] = (source.position.y + source.size.y) * texpixel_size.y;
- if (pline->triangle_colors.size() == 1) {
- single = true;
- color = *p_colors;
- } else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
- } else {
- single = false;
- }
+ buffer[(3 * 4 * 4) + 12] = np->rect.position.x + np->rect.size.x;
+ buffer[(3 * 4 * 4) + 13] = np->rect.position.y + np->rect.size.y;
- const bool use_single_color = single;
- const Color single_color = color;
+ buffer[(3 * 4 * 4) + 14] = (source.position.x + source.size.x) * texpixel_size.x;
+ buffer[(3 * 4 * 4) + 15] = (source.position.y + source.size.y) * texpixel_size.y;
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ // print_line(String::num((source.position.y + source.size.y) * texpixel_size.y));
+ }
- v->uv = Vector2();
- v->v = t[i];
+ glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(float) * (16 + 16) * 2, buffer);
- ++v;
- }
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);
- for (int i = 0; i < p_triangle_count; ++i) {
- const int indices[3] = {
- i, i + 1, i + 2
- };
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset + i * 3, indices, sizeof(indices));
- }
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (uint8_t *)0 + (sizeof(float) * 2));
- _commit(p_vertex_count, p_index_count);
- } else {
- _begin(GL_LINES);
+ glDrawElements(GL_TRIANGLES, 18 * 3 - (np->draw_center ? 0 : 6), GL_UNSIGNED_BYTE, NULL);
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- const Color *p_colors = pline->line_colors.ptr();
+ } break;
- bool single;
- Color color;
+ case Item::Command::TYPE_CIRCLE: {
- if (pline->line_colors.size() == 1) {
- single = true;
- color = *p_colors;
- } else if (!p_colors) {
- single = true;
- color = Color(1, 1, 1, 1);
- } else {
- single = false;
- }
+ Item::CommandCircle *circle = static_cast<Item::CommandCircle *>(command);
- const bool use_single_color = single;
- const Color single_color = color;
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
- const Vector2 *p_lines = pline->lines.ptr();
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- if (pline->multiline) {
- const int p_lines_count = pline->lines.size() / 2;
+ static const int num_points = 32;
- for (int i = 0; i < p_lines_count; ++i) {
- const int p_vertex_count = 2;
- const int p_index_count = 2;
+ Vector2 points[num_points + 1];
+ points[num_points] = circle->pos;
- _prepare(p_vertex_count, p_index_count);
+ int indices[num_points * 3];
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ for (int i = 0; i < num_points; i++) {
+ points[i] = circle->pos + Vector2(Math::sin(i * Math_PI * 2.0 / num_points), Math::cos(i * Math_PI * 2.0 / num_points)) * circle->radius;
+ indices[i * 3 + 0] = i;
+ indices[i * 3 + 1] = (i + 1) % num_points;
+ indices[i * 3 + 2] = num_points;
+ }
- for (int j = 0; j < 2; ++j) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ _bind_canvas_texture(RID(), RID());
- v->uv = Vector2();
- v->v = p_lines[i * 2 + j];
+ _draw_polygon(indices, num_points * 3, num_points + 1, points, NULL, &circle->color, true);
+ } break;
- ++v;
- }
+ case Item::Command::TYPE_POLYGON: {
- const int indices[p_index_count] = { 0, 1 };
+ Item::CommandPolygon *polygon = static_cast<Item::CommandPolygon *>(command);
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset, indices, sizeof(indices));
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
- _commit(p_vertex_count, p_index_count);
- }
- } else {
- const int p_vertex_count = pline->lines.size();
- const int p_lines_count = p_vertex_count - 1;
- const int p_index_count = p_lines_count * 2;
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- _prepare(p_vertex_count, p_index_count);
+ RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(polygon->texture, polygon->normal_map);
- _bind_shader(p_material);
- _bind_canvas_texture(RID(), RID());
+ if (texture) {
+ Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
+ }
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
+ _draw_polygon(polygon->indices.ptr(), polygon->count, polygon->points.size(), polygon->points.ptr(), polygon->uvs.ptr(), polygon->colors.ptr(), polygon->colors.size() == 1);
+ } break;
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
+ case Item::Command::TYPE_POLYLINE: {
+ Item::CommandPolyLine *pline = static_cast<Item::CommandPolyLine *>(command);
- v->uv = Vector2();
- v->v = p_lines[i];
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
- ++v;
- }
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
- for (int i = 0; i < p_lines_count; ++i) {
- const int indices[2] = { i, i + 1 };
+ _bind_canvas_texture(RID(), RID());
- memcpy(data.mem_index_buffer + data.mem_index_buffer_offset + i * 2, indices, sizeof(indices));
+ if (pline->triangles.size()) {
+ _draw_generic(GL_TRIANGLE_STRIP, pline->triangles.size(), pline->triangles.ptr(), NULL, pline->triangle_colors.ptr(), pline->triangle_colors.size() == 1);
+ } else {
+ if (pline->multiline) {
+ int todo = pline->lines.size() / 2;
+ int max_per_call = data.polygon_buffer_size / (sizeof(real_t) * 4);
+ int offset = 0;
+
+ while (todo) {
+ int to_draw = MIN(max_per_call, todo);
+ _draw_generic(GL_LINES, to_draw * 2, &pline->lines.ptr()[offset], NULL, pline->line_colors.size() == 1 ? pline->line_colors.ptr() : &pline->line_colors.ptr()[offset], pline->line_colors.size() == 1);
+ todo -= to_draw;
+ offset += to_draw * 2;
}
-
- _commit(p_vertex_count, p_index_count);
+ } else {
+ _draw_generic(GL_LINES, pline->lines.size(), pline->lines.ptr(), NULL, pline->line_colors.ptr(), pline->line_colors.size() == 1);
}
}
} break;
case Item::Command::TYPE_PRIMITIVE: {
+
Item::CommandPrimitive *primitive = static_cast<Item::CommandPrimitive *>(command);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, true);
- const GLenum prim[5] = { GL_POINTS, GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN };
+ if (state.canvas_shader.bind()) {
+ _set_uniforms();
+ state.canvas_shader.use_material((void *)p_material);
+ }
ERR_CONTINUE(primitive->points.size() < 1);
- _bind_shader(p_material);
RasterizerStorageGLES2::Texture *texture = _bind_canvas_texture(primitive->texture, primitive->normal_map);
if (texture) {
Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height);
- state.uniforms.texpixel_size = texpixel_size;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::COLOR_TEXPIXEL_SIZE, texpixel_size);
}
- const int p_vertex_count = primitive->points.size();
- const int p_index_count = p_vertex_count;
-
- _begin(prim[p_vertex_count]);
- _prepare(p_vertex_count, p_index_count);
-
- Vertex *v = data.mem_vertex_buffer + data.mem_vertex_buffer_offset;
- int *index = data.mem_index_buffer + data.mem_index_buffer_offset;
-
- Color c;
- bool p_single_color;
-
- const Color *p_colors = primitive->colors.ptr();
- const Vector2 *p_uvs = primitive->uvs.ptr();
- const Vector2 *p_points = primitive->points.ptr();
-
if (primitive->colors.size() == 1 && primitive->points.size() > 1) {
- p_single_color = true;
- c = primitive->colors[0];
+ Color c = primitive->colors[0];
+ glVertexAttrib4f(VS::ARRAY_COLOR, c.r, c.g, c.b, c.a);
} else if (primitive->colors.empty()) {
- p_single_color = true;
- c = Color(1, 1, 1, 1);
- } else {
- p_single_color = false;
- }
-
- const bool use_single_color = p_single_color;
- const Color single_color = c;
-
- for (int i = 0; i < p_vertex_count; ++i) {
- if (use_single_color)
- v->c = single_color;
- else
- v->c = p_colors[i];
-
- if (p_uvs)
- v->uv = p_uvs[i];
- else
- v->uv = Vector2();
-
- v->v = p_points[i];
-
- index[i] = i;
-
- ++v;
+ glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1);
}
- _commit(p_vertex_count, p_index_count);
+ _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr());
} break;
case Item::Command::TYPE_TRANSFORM: {
Item::CommandTransform *transform = static_cast<Item::CommandTransform *>(command);
state.uniforms.extra_matrix = transform->xform;
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX, state.uniforms.extra_matrix);
} break;
case Item::Command::TYPE_PARTICLES: {
@@ -859,7 +816,6 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex);
- data.texture = storage->resources.white_tex;
int last_blend_mode = -1;
@@ -869,9 +825,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
Item *ci = p_item_list;
- Item *material_owner = ci->material_owner ? ci->material_owner : ci;
-
if (current_clip != ci->final_clip_owner) {
+
current_clip = ci->final_clip_owner;
if (current_clip) {
@@ -895,6 +850,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
}
}
+ Item *material_owner = ci->material_owner ? ci->material_owner : ci;
+
RID material = material_owner->material;
RasterizerStorageGLES2::Material *material_ptr = storage->material_owner.getornull(material);
@@ -1024,10 +981,8 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
state.uniforms.extra_matrix = Transform2D();
_set_uniforms();
- _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
- // TODO: figure out when to _flush to get better batching results
- _flush();
+ _canvas_item_render_commands(p_item_list, NULL, reclip, material_ptr);
rebind_shader = true; // hacked in for now.
@@ -1042,8 +997,6 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
p_item_list = p_item_list->next;
}
- _flush();
-
if (current_clip) {
glDisable(GL_SCISSOR_TEST);
}
@@ -1082,40 +1035,17 @@ void RasterizerCanvasGLES2::reset_canvas() {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
-void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &dst_rect, const Rect2 &src_rect) {
-
- const int p_index_count = 6;
- const int p_vertex_count = 4;
-
- Vertex v[p_vertex_count];
- Color c(1, 1, 1, 1);
-
- // 0,0
- v[0].v = dst_rect.position;
- v[0].c = c;
- v[0].uv = src_rect.position;
-
- // 0,1
- v[1].v = Vector2(dst_rect.position.x, dst_rect.position.y + dst_rect.size.y);
- v[1].c = c;
- v[1].uv = Vector2(src_rect.position.x, src_rect.position.y + src_rect.size.y);
-
- // 1,1
- v[2].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y + dst_rect.size.y);
- v[2].c = c;
- v[2].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y + src_rect.size.y);
-
- // 1,0
- v[3].v = Vector2(dst_rect.position.x + dst_rect.size.x, dst_rect.position.y);
- v[3].c = c;
- v[3].uv = Vector2(src_rect.position.x + src_rect.size.x, src_rect.position.y);
+void RasterizerCanvasGLES2::_bind_quad_buffer() {
+ glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
+ glEnableVertexAttribArray(VS::ARRAY_VERTEX);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL);
+}
+void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) {
- const int indices[p_index_count] = {
- 0, 1, 2,
- 2, 3, 0
- };
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::DST_RECT, Color(p_rect.position.x, p_rect.position.y, p_rect.size.x, p_rect.size.y));
+ state.canvas_shader.set_uniform(CanvasShaderGLES2::SRC_RECT, Color(p_src.position.x, p_src.position.y, p_src.size.x, p_src.size.y));
- _draw(GL_TRIANGLES, p_vertex_count, v, p_index_count, indices);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_image) {
@@ -1123,36 +1053,60 @@ void RasterizerCanvasGLES2::draw_window_margins(int *black_margin, RID *black_im
void RasterizerCanvasGLES2::initialize() {
+ // quad buffer
+ {
+ glGenBuffers(1, &data.canvas_quad_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices);
+
+ const float qv[8] = {
+ 0, 0,
+ 0, 1,
+ 1, 1,
+ 1, 0
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, qv, GL_STATIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ }
+
// polygon buffer
{
uint32_t poly_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_buffer_size_kb", 128);
poly_size *= 1024;
poly_size = MAX(poly_size, (2 + 2 + 4) * 4 * sizeof(float));
- glGenBuffers(1, &data.vertex_buffer);
- glBindBuffer(GL_ARRAY_BUFFER, data.vertex_buffer);
+ glGenBuffers(1, &data.polygon_buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, data.polygon_buffer);
glBufferData(GL_ARRAY_BUFFER, poly_size, NULL, GL_DYNAMIC_DRAW);
- data.vertex_buffer_size = poly_size;
+ data.polygon_buffer_size = poly_size;
glBindBuffer(GL_ARRAY_BUFFER, 0);
uint32_t index_size = GLOBAL_DEF("rendering/limits/buffers/canvas_polygon_index_size_kb", 128);
index_size *= 1024; // kb
- glGenBuffers(1, &data.index_buffer);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.index_buffer);
+ glGenBuffers(1, &data.polygon_index_buffer);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_size, NULL, GL_DYNAMIC_DRAW);
-
- data.index_buffer_size = index_size;
-
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
// ninepatch buffers
{
// array buffer
+ glGenBuffers(1, &data.ninepatch_vertices);
+ glBindBuffer(GL_ARRAY_BUFFER, data.ninepatch_vertices);
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * (16 + 16) * 2, NULL, GL_DYNAMIC_DRAW);
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ // element buffer
+ glGenBuffers(1, &data.ninepatch_elements);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements);
#define _EIDX(y, x) (y * 4 + x)
- const int elems[3 * 2 * 9] = {
+ uint8_t elems[3 * 2 * 9] = {
// first row
@@ -1196,25 +1150,15 @@ void RasterizerCanvasGLES2::initialize() {
;
#undef _EIDX
- memcpy(data.ninepatch_elements, elems, sizeof(elems));
- }
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elems), elems, GL_STATIC_DRAW);
- {
- const uint32_t size = data.vertex_buffer_size / sizeof(Vertex);
- data.mem_vertex_buffer = (Vertex *)memalloc(sizeof(Vertex) * size);
- data.mem_vertex_buffer_offset = 0;
- data.mem_vertex_buffer_size = size;
- }
-
- {
- const uint32_t size = data.index_buffer_size / sizeof(int);
- data.mem_index_buffer = (int *)memalloc(sizeof(int) * size);
- data.mem_index_buffer_offset = 0;
- data.mem_index_buffer_size = size;
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
state.canvas_shader.init();
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+
state.canvas_shader.bind();
}
@@ -1223,92 +1167,3 @@ void RasterizerCanvasGLES2::finalize() {
RasterizerCanvasGLES2::RasterizerCanvasGLES2() {
}
-
-void RasterizerCanvasGLES2::_begin(const GLuint p_primitive) {
- if (data.primitive != p_primitive) {
- _flush();
- data.primitive = p_primitive;
- }
-}
-
-void RasterizerCanvasGLES2::_prepare(const int p_vertex_count, const int p_index_count) {
- if (data.mem_vertex_buffer_size - data.mem_vertex_buffer_offset < p_vertex_count ||
- data.mem_index_buffer_size - data.mem_index_buffer_offset < p_index_count) {
- _flush();
- }
-}
-
-void RasterizerCanvasGLES2::_draw(const GLuint p_primitive, const int p_vertex_count, const Vertex *p_vertices, const int p_index_count, const int *p_indices) {
- glBindBuffer(GL_ARRAY_BUFFER, data.vertex_buffer);
- glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vertex) * p_vertex_count, p_vertices);
-
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.index_buffer);
- glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(int) * p_index_count, p_indices);
-
- glEnableVertexAttribArray(VS::ARRAY_VERTEX);
- glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), NULL);
-
- glEnableVertexAttribArray(VS::ARRAY_COLOR);
- glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), ((uint8_t *)0) + sizeof(Vector2));
-
- glEnableVertexAttribArray(VS::ARRAY_TEX_UV);
- glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), ((uint8_t *)0) + sizeof(Vector2) + sizeof(Color));
-
- glDrawElements(p_primitive, p_index_count, GL_UNSIGNED_INT, 0);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
-}
-
-void RasterizerCanvasGLES2::_flush() {
- if (data.mem_vertex_buffer_offset) {
- _draw(data.primitive, data.mem_vertex_buffer_offset, data.mem_vertex_buffer, data.mem_index_buffer_offset, data.mem_index_buffer);
- }
-
- data.mem_vertex_buffer_offset = 0;
- data.mem_index_buffer_offset = 0;
-}
-
-void RasterizerCanvasGLES2::_commit(const int p_vertex_count, const int p_index_count) {
- ERR_FAIL_COND(!p_vertex_count);
- ERR_FAIL_COND(!p_index_count);
-
- if (state.uniforms.extra_matrix != state.prev_uniforms.extra_matrix ||
- state.uniforms.final_modulate != state.prev_uniforms.final_modulate ||
- state.uniforms.modelview_matrix != state.prev_uniforms.modelview_matrix ||
- state.uniforms.projection_matrix != state.prev_uniforms.projection_matrix ||
- state.uniforms.texpixel_size != state.prev_uniforms.texpixel_size ||
- state.uniforms.time != state.prev_uniforms.time) {
-
- _set_uniforms();
- state.prev_uniforms = state.uniforms;
- _flush();
- }
-
- const int new_index_offset = data.mem_index_buffer_offset + p_index_count;
-
- for (int i = data.mem_index_buffer_offset; i < new_index_offset; ++i)
- data.mem_index_buffer[i] += data.mem_vertex_buffer_offset;
-
- data.mem_vertex_buffer_offset += p_vertex_count;
- data.mem_index_buffer_offset = new_index_offset;
-}
-
-void RasterizerCanvasGLES2::_untile() {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- state.tiled = false;
-}
-
-void RasterizerCanvasGLES2::_bind_shader(RasterizerStorageGLES2::Material *p_material) {
- if (!state.canvas_shader.is_dirty()) {
- return;
- }
-
- _flush();
-
- if (state.canvas_shader.bind()) {
- state.canvas_shader.use_material((void *)p_material);
- }
-}
diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h
index d5a122e533..cda3ec79e7 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.h
+++ b/drivers/gles2/rasterizer_canvas_gles2.h
@@ -50,44 +50,23 @@ public:
Color final_modulate;
float time;
-
- Size2 texpixel_size;
- };
-
- struct Vertex {
- Vector2 v;
- Color c;
- Vector2 uv;
};
struct Data {
- GLuint vertex_buffer;
- GLuint index_buffer;
-
- uint32_t vertex_buffer_size;
- uint32_t index_buffer_size;
-
- int ninepatch_elements[3 * 2 * 9];
+ GLuint canvas_quad_vertices;
+ GLuint polygon_buffer;
+ GLuint polygon_index_buffer;
- int *mem_index_buffer;
- uint32_t mem_index_buffer_offset;
- uint32_t mem_index_buffer_size;
+ uint32_t polygon_buffer_size;
- Vertex *mem_vertex_buffer;
- uint32_t mem_vertex_buffer_offset;
- uint32_t mem_vertex_buffer_size;
+ GLuint ninepatch_vertices;
+ GLuint ninepatch_elements;
- GLuint primitive;
- GLuint texture;
} data;
struct State {
Uniforms uniforms;
- Uniforms prev_uniforms;
-
- bool tiled;
-
bool canvas_texscreen_used;
CanvasShaderGLES2 canvas_shader;
// CanvasShadowShaderGLES3 canvas_shadow_shader;
@@ -120,16 +99,9 @@ public:
_FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false);
+ _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs);
_FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
-
- _FORCE_INLINE_ void _begin(const GLuint p_primitive);
- _FORCE_INLINE_ void _prepare(const int p_vertex_count, const int p_index_count);
- _FORCE_INLINE_ void _commit(const int p_vertex_count, const int p_index_count);
-
- _FORCE_INLINE_ void _flush();
- _FORCE_INLINE_ void _draw(const GLuint p_primitive, const int p_vertex_count, const Vertex *p_vertices, const int p_index_count, const int *p_indices);
-
- _FORCE_INLINE_ void _untile();
+ _FORCE_INLINE_ void _draw_generic(GLuint p_primitive, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor);
_FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip, RasterizerStorageGLES2::Material *p_material);
_FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect);
@@ -142,8 +114,8 @@ public:
virtual void reset_canvas();
RasterizerStorageGLES2::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map);
- _FORCE_INLINE_ void _bind_shader(RasterizerStorageGLES2::Material *p_material);
+ void _bind_quad_buffer();
void draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src);
void initialize();
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 165ffc0412..a1a0b9e2c6 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -345,6 +345,9 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
RasterizerStorageGLES2::RenderTarget *rt = storage->render_target_owner.getornull(p_render_target);
ERR_FAIL_COND(!rt);
+ canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, true);
+ canvas->state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_UV_ATTRIBUTE, false);
+
canvas->state.canvas_shader.set_custom_shader(0);
canvas->state.canvas_shader.bind();
@@ -356,7 +359,7 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
// TODO normals
- canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 1, 1, -1));
+ canvas->draw_generic_textured_rect(p_screen_rect, Rect2(0, 0, 1, -1));
glBindTexture(GL_TEXTURE_2D, 0);
canvas->canvas_end();
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 38c0ccaac2..c1fbf73254 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -252,7 +252,7 @@ public:
int mipmaps;
bool active;
- GLuint tex_id;
+ GLenum tex_id;
uint16_t stored_cube_sides;
@@ -429,8 +429,6 @@ public:
bool uses_screen_texture;
bool uses_screen_uv;
bool uses_time;
- bool uses_modelview_matrix;
- bool uses_vertex;
} canvas_item;
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index 89c1b6490d..e9b58cb272 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -122,11 +122,13 @@ GLint ShaderGLES2::get_uniform_location(int p_index) const {
}
bool ShaderGLES2::bind() {
- if (!is_dirty())
- return false;
- conditional_version = new_conditional_version;
- version = get_current_version();
+ if (active != this || !version || new_conditional_version.key != conditional_version.key) {
+ conditional_version = new_conditional_version;
+ version = get_current_version();
+ } else {
+ return false;
+ }
ERR_FAIL_COND_V(!version, false);
@@ -1107,7 +1109,3 @@ ShaderGLES2::ShaderGLES2() {
ShaderGLES2::~ShaderGLES2() {
finish();
}
-
-bool ShaderGLES2::is_dirty() const {
- return active != this || !version || new_conditional_version.key != conditional_version.key;
-}
diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h
index 99513abfe9..cb515c199c 100644
--- a/drivers/gles2/shader_gles2.h
+++ b/drivers/gles2/shader_gles2.h
@@ -208,7 +208,6 @@ public:
GLint get_uniform_location(int p_index) const;
static _FORCE_INLINE_ ShaderGLES2 *get_active() { return active; }
- bool is_dirty() const;
bool bind();
void unbind();
void bind_uniforms();
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index a63c7675d8..29d81bb2c4 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -20,6 +20,13 @@ varying vec4 color_interp;
uniform highp vec2 color_texpixel_size;
+#ifdef USE_TEXTURE_RECT
+
+uniform vec4 dst_rect;
+uniform vec4 src_rect;
+
+#endif
+
uniform highp float time;
VERTEX_SHADER_GLOBALS
@@ -37,9 +44,35 @@ void main() {
vec4 color = color_attrib;
+#ifdef USE_TEXTURE_RECT
+
+ if (dst_rect.z < 0.0) { // Transpose is encoded as negative dst_rect.z
+ uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.yx;
+ } else {
+ uv_interp = src_rect.xy + abs(src_rect.zw) * vertex;
+ }
+
+ vec4 outvec = vec4(0.0, 0.0, 0.0, 1.0);
+
+ // This is what is done in the GLES 3 bindings and should
+ // take care of flipped rects.
+ //
+ // But it doesn't.
+ // I don't know why, will need to investigate further.
+
+ outvec.xy = dst_rect.xy + abs(dst_rect.zw) * select(vertex, vec2(1.0, 1.0) - vertex, lessThan(src_rect.zw, vec2(0.0, 0.0)));
+
+ // outvec.xy = dst_rect.xy + abs(dst_rect.zw) * vertex;
+#else
vec4 outvec = vec4(vertex.xy, 0.0, 1.0);
+#ifdef USE_UV_ATTRIBUTE
uv_interp = uv_attrib;
+#else
+ uv_interp = vertex.xy;
+#endif
+
+#endif
{
vec2 src_vtx=outvec.xy;