1 /* the geometry context must always be bound before calling geometry_ functions */
4 _cairo_gpu_geometry_begin
6 _cairo_gpu_geometry_end
15 _cairo_gpu_geometry_put
18 static inline cairo_gpu_geometry_t
*
19 _cairo_gpu_geometry_init(cairo_gpu_geometry_t
* geometry
)
24 geometry
->vbo_size
= 0;
26 geometry
->data_size
= 0;
30 static inline cairo_gpu_geometry_t
*
31 _cairo_gpu_geometry_fini_vbo(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
)
35 if(geometry
->flags
& GEOM_VBO_MAPPED
)
36 ctx
->gl
.UnmapBufferARB(GL_ARRAY_BUFFER
);
39 ctx
->gl
.DeleteBuffersARB(1, &geometry
->vbo
);
41 geometry
->vbo_size
= 0;
47 ctx
->gl
.DeleteVertexArrays(1, &geometry
->vao
);
56 static inline cairo_gpu_geometry_t
*
57 _cairo_gpu_geometry_fini(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
)
63 geometry
->data_size
= 0;
66 return _cairo_gpu_geometry_fini_vbo(ctx
, geometry
);
70 _cairo_gpu_geometry_begin(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
, unsigned mode
, int count
, int vert
, int color
, int tex
)
72 unsigned size
= count
* ((vert
+ !!color
+ tex
) * sizeof(float));
74 _cairo_gpu_geometry_fini_vbo(ctx
, geometry
);
76 geometry
->id
= _cairo_id();
77 geometry
->mode
= mode
;
78 geometry
->vert
= vert
;
79 geometry
->color
= color
;
82 geometry
->flags
&=~ GEOM_SETUP
;
84 assert(!(geometry
->flags
& GEOM_VBO_MAPPED
));
86 // it seems VBOs are a win for large buffers, but a loss for small ones...
87 // TODO: maybe apply some threshold to use VBOs
88 if(ctx
->space
->use_vbo
)
93 ctx
->gl
.GenBuffersARB(1, &geometry
->vbo
);
97 if(geometry
->id
!= ctx
->vbo_id
)
99 ctx
->gl
.BindBufferARB(GL_ARRAY_BUFFER
, geometry
->vbo
);
100 ctx
->vbo_id
= geometry
->id
;
103 if(geometry
->vbo_size
< size
)
105 if(!geometry
->vbo_size
)
106 geometry
->vbo_size
= 1;
107 while(geometry
->vbo_size
< size
)
108 geometry
->vbo_size
<<= 1;
109 ctx
->gl
.BufferDataARB(GL_ARRAY_BUFFER
, geometry
->vbo_size
, 0, GL_STREAM_DRAW
);
112 #ifdef GLEW_ARB_map_buffer_range
113 if(GLEW_ARB_map_buffer_range
)
114 p
= ctx
->gl
.MapBufferRange(GL_ARRAY_BUFFER
, 0, size
, GL_MAP_WRITE_BIT
| GL_MAP_INVALIDATE_BUFFER_BIT
);
117 p
= ctx
->gl
.MapBufferARB(GL_ARRAY_BUFFER
, GL_WRITE_ONLY
);
122 geometry
->flags
|= GEOM_VBO_MAPPED
;
127 fprintf(stderr
, "vbo create/map failed for %i! fallback!\n", size
);
131 if(geometry
->data_size
< size
)
133 if(!geometry
->data_size
)
134 geometry
->data_size
= 1;
135 while(geometry
->data_size
< size
)
136 geometry
->data_size
<<= 1;
138 free(geometry
->data
);
140 geometry
->data
= malloc(geometry
->data_size
);
143 return geometry
->data
;
147 _cairo_gpu_geometry_end(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
, int count
)
149 int size
= count
* ((geometry
->vert
+ geometry
->tex
+ !!geometry
->color
) * sizeof(float));
151 geometry
->count
= count
;
154 if(geometry
->id
!= ctx
->vbo_id
)
156 ctx
->gl
.BindBufferARB(GL_ARRAY_BUFFER
, (unsigned)geometry
->vbo
);
157 ctx
->vbo_id
= geometry
->id
;
160 if(geometry
->flags
& GEOM_VBO_MAPPED
)
162 ctx
->gl
.UnmapBufferARB(GL_ARRAY_BUFFER
);
163 geometry
->flags
&= ~GEOM_VBO_MAPPED
;
166 ctx
->gl
.BufferDataARB(GL_ARRAY_BUFFER
, size
, geometry
->data
, GL_STREAM_DRAW
);
171 _cairo_gpu_geometry__do_bind(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
)
175 int vert
= geometry
->vert
;
176 int tex
= geometry
->tex
;
177 int color
= geometry
->color
;
179 // XXX: fix and reenable VAO support
180 //if(0 && !geometry->vao && GLEW_ARB_vertex_array_object)
183 ctx
->gl
.GenVertexArrays(1, &geometry
->vao
);
186 ctx
->gl
.BindVertexArray(geometry
->vao
);
187 ctx
->vao_id
= geometry
->id
;
191 if(geometry
->id
!= ctx
->vbo_id
)
193 ctx
->gl
.BindBufferARB(GL_ARRAY_BUFFER
, (unsigned)geometry
->vbo
);
194 ctx
->vbo_id
= geometry
->id
;
200 base
= (char *)geometry
->data
;
202 stride
= (vert
+ !!color
+ tex
) * sizeof(float);
205 ctx
->gl
.VertexPointer(vert
, GL_FLOAT
, stride
, base
);
206 if(!ctx
->vertex_array
)
208 ctx
->gl
.EnableClientState(GL_VERTEX_ARRAY
);
209 ctx
->vertex_array
= 1;
214 if(ctx
->vertex_array
)
216 ctx
->gl
.DisableClientState(GL_VERTEX_ARRAY
);
217 ctx
->vertex_array
= 0;
223 ctx
->gl
.ColorPointer(color
, GL_UNSIGNED_BYTE
, stride
, base
+ vert
* sizeof(float));
224 if(!ctx
->color_array
)
226 ctx
->gl
.EnableClientState(GL_COLOR_ARRAY
);
227 ctx
->color_array
= 1;
234 ctx
->gl
.DisableClientState(GL_COLOR_ARRAY
);
235 ctx
->color_array
= 0;
239 // TODO: this is an hack for show_glyphs, we should maybe do it more generally?
242 ctx
->gl
.ClientActiveTextureARB(GL_TEXTURE0
);
243 ctx
->gl
.TexCoordPointer(tex
, GL_FLOAT
, stride
, base
+ (vert
+ !!color
) * sizeof(float));
245 ctx
->gl
.EnableClientState(GL_TEXTURE_COORD_ARRAY
);
246 ctx
->gl
.ClientActiveTextureARB(GL_TEXTURE1
);
247 ctx
->gl
.TexCoordPointer(tex
, GL_FLOAT
, stride
, base
+ (vert
+ !!color
) * sizeof(float));
250 ctx
->gl
.EnableClientState(GL_TEXTURE_COORD_ARRAY
);
258 ctx
->gl
.ClientActiveTextureARB(GL_TEXTURE0
);
259 ctx
->gl
.DisableClientState(GL_TEXTURE_COORD_ARRAY
);
260 ctx
->gl
.ClientActiveTextureARB(GL_TEXTURE1
);
261 ctx
->gl
.DisableClientState(GL_TEXTURE_COORD_ARRAY
);
268 _cairo_gpu_geometry_bind(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
)
272 if(ctx
->vao_id
!= geometry
->id
)
274 ctx
->gl
.BindVertexArray(geometry
->vao
);
275 ctx
->vao_id
= geometry
->id
;
282 ctx
->gl
.BindVertexArray(0);
286 if(ctx
->vao0_id
!= geometry
->id
)
288 geometry
->flags
&= ~GEOM_SETUP
;
289 ctx
->vao0_id
= geometry
->id
;
293 ctx
->mode
= geometry
->mode
;
294 ctx
->count
= geometry
->count
;
296 if(geometry
->flags
& GEOM_SETUP
)
299 _cairo_gpu_geometry__do_bind(ctx
, geometry
);
304 _cairo_gpu_geometry_put(cairo_gpu_context_t
* ctx
, cairo_gpu_geometry_t
* geometry
)
306 if(geometry
->vbo
&& (geometry
->vbo_size
> 256 * 1024))
308 if(geometry
->vbo
!= ctx
->vbo
)
310 ctx
->gl
.BindBufferARB(GL_ARRAY_BUFFER
, (unsigned)geometry
->vbo
);
311 ctx
->vbo
= geometry
->vbo
;
314 // this seems to sometimes fail on nVidia (why?!)
315 ctx
->gl
.BufferDataARB(GL_ARRAY_BUFFER
, 0, 0, GL_STREAM_DRAW
);
316 while(ctx
->gl
.GetError())
319 geometry
->vbo_size
= 0;
325 static inline cairo_geometry_t*
326 _cairo_gpu_space_create_geometry(cairo_gpu_space_t* space)
328 cairo_gpu_user_geometry_t* geometry = (cairo_gpu_geometry_t*)malloc(sizeof(cairo_gpu_user_geometry_t));
329 geometry->space = space;
330 _cairo_gpu_geometry_init(&geometry->geometry, space);
331 return &geometry->base;
335 _cairo_gpu_geometry_destroy(cairo_gpu_user_geometry_t* geometry)
337 cairo_gpu_context_t* ctx = cairo_space_bind(geometry->space);
338 _cairo_gpu_geometry_fini(ctx, &geometry->geometry);