5 #define DEGPERRAD 57.2957795f 9 #define RADPERDEG 0.0174532925f 19 #define BEGIN_UNTEXTURED(function_name, shape, num_additional_vertices, num_additional_indices) \ 20 GPU_CONTEXT_DATA* cdata; \ 22 unsigned short* index_buffer; \ 26 unsigned short blit_buffer_starting_index; \ 29 GPU_PushErrorCode(function_name, GPU_ERROR_NULL_ARGUMENT, "target"); \ 32 if(renderer != target->renderer) \ 34 GPU_PushErrorCode(function_name, GPU_ERROR_USER_ERROR, "Mismatched renderer"); \ 38 makeContextCurrent(renderer, target); \ 39 if(renderer->current_context_target == NULL) \ 41 GPU_PushErrorCode(function_name, GPU_ERROR_USER_ERROR, "NULL context"); \ 45 if(!bindFramebuffer(renderer, target)) \ 47 GPU_PushErrorCode(function_name, GPU_ERROR_BACKEND_ERROR, "Failed to bind framebuffer."); \ 51 prepareToRenderToTarget(renderer, target); \ 52 prepareToRenderShapes(renderer, shape); \ 54 cdata = (GPU_CONTEXT_DATA*)renderer->current_context_target->context->data; \ 56 if(cdata->blit_buffer_num_vertices + (num_additional_vertices) >= cdata->blit_buffer_max_num_vertices) \ 58 if(!growBlitBuffer(cdata, cdata->blit_buffer_num_vertices + (num_additional_vertices))) \ 59 renderer->impl->FlushBlitBuffer(renderer); \ 61 if(cdata->index_buffer_num_vertices + (num_additional_indices) >= cdata->index_buffer_max_num_vertices) \ 63 if(!growIndexBuffer(cdata, cdata->index_buffer_num_vertices + (num_additional_indices))) \ 64 renderer->impl->FlushBlitBuffer(renderer); \ 67 blit_buffer = cdata->blit_buffer; \ 68 index_buffer = cdata->index_buffer; \ 70 vert_index = GPU_BLIT_BUFFER_VERTEX_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \ 71 color_index = GPU_BLIT_BUFFER_COLOR_OFFSET + cdata->blit_buffer_num_vertices*GPU_BLIT_BUFFER_FLOATS_PER_VERTEX; \ 73 if(target->use_color) \ 75 r = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.r, color.r); \ 76 g = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.g, color.g); \ 77 b = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(target->color.b, color.b); \ 78 a = MIX_COLOR_COMPONENT_NORMALIZED_RESULT(GET_ALPHA(target->color), GET_ALPHA(color)); \ 85 a = GET_ALPHA(color)/255.0f; \ 87 blit_buffer_starting_index = cdata->blit_buffer_num_vertices; \ 88 (void)blit_buffer_starting_index; 94 static float SetLineThickness(
GPU_Renderer* renderer,
float thickness)
103 renderer->
impl->FlushBlitBuffer(renderer);
106 #ifndef SDL_GPU_SKIP_LINE_WIDTH 107 glLineWidth(thickness);
124 static void Line(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2, SDL_Color color)
126 float thickness = GetLineThickness(renderer);
128 float t = thickness/2;
129 float line_angle = atan2f(y2 - y1, x2 - x1);
130 float tc = t*cosf(line_angle);
131 float ts = t*sinf(line_angle);
145 static void Circle(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius, SDL_Color color);
147 static void Arc(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius,
float start_angle,
float end_angle, SDL_Color color)
152 float t = GetLineThickness(renderer)/2;
153 float inner_radius = radius - t;
154 float outer_radius = radius + t;
162 if(inner_radius < 0.0f)
165 if(start_angle > end_angle)
167 float swapa = end_angle;
168 end_angle = start_angle;
171 if(start_angle == end_angle)
175 if(end_angle - start_angle >= 360)
177 Circle(renderer, target, x, y, radius, color);
182 while(start_angle < 0 && end_angle < 0)
187 while(start_angle > 360 && end_angle > 360)
194 dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(outer_radius));
196 numSegments = (fabs(end_angle - start_angle)*
M_PI/180)/dt;
201 BEGIN_UNTEXTURED(
"GPU_Arc", GL_TRIANGLES, 2*(numSegments), 6*(numSegments));
207 start_angle *=
M_PI/180;
208 dx = cos(start_angle);
209 dy = sin(start_angle);
213 for (i = 1; i < numSegments; i++)
215 tempx = c * dx - s * dy;
216 dy = s * dx + c * dy;
218 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
222 end_angle *=
M_PI/180;
225 END_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
230 static void CircleFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius, SDL_Color color);
232 static void ArcFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius,
float start_angle,
float end_angle, SDL_Color color)
243 if(start_angle > end_angle)
245 float swapa = end_angle;
246 end_angle = start_angle;
249 if(start_angle == end_angle)
253 if(end_angle - start_angle >= 360)
255 CircleFilled(renderer, target, x, y, radius, color);
260 while(start_angle < 0 && end_angle < 0)
265 while(start_angle > 360 && end_angle > 360)
271 dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(radius));
273 numSegments = (fabs(end_angle - start_angle)*
M_PI/180)/dt;
278 BEGIN_UNTEXTURED(
"GPU_ArcFilled", GL_TRIANGLES, 3 + (numSegments - 1) + 1, 3 + (numSegments - 1) * 3 + 3);
284 start_angle *=
M_PI/180;
285 dx = cos(start_angle);
286 dy = sin(start_angle);
292 tempx = c * dx - s * dy;
293 dy = s * dx + c * dy;
297 for (i = 2; i < numSegments + 1; i++)
299 tempx = c * dx - s * dy;
300 dy = s * dx + c * dy;
308 end_angle *=
M_PI/180;
322 static void Circle(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius, SDL_Color color)
324 float thickness = GetLineThickness(renderer);
327 float t = thickness/2;
328 float inner_radius = radius - t;
329 float outer_radius = radius + t;
330 float dt = (1.25f/sqrtf(outer_radius));
331 int numSegments = 2*
M_PI/dt+1;
337 BEGIN_UNTEXTURED(
"GPU_Circle", GL_TRIANGLES, 2*(numSegments), 6*(numSegments));
339 if(inner_radius < 0.0f)
347 for(i = 1; i < numSegments; i++)
349 tempx = c * dx - s * dy;
350 dy = s * dx + c * dy;
353 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
359 static void CircleFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float radius, SDL_Color color)
361 float dt = (1.25f/sqrtf(radius));
363 int numSegments = 2*
M_PI/dt+1;
370 BEGIN_UNTEXTURED(
"GPU_CircleFilled", GL_TRIANGLES, 3 + (numSegments-2), 3 + (numSegments-2)*3 + 3);
379 tempx = c * dx - s * dy;
380 dy = s * dx + c * dy;
384 for(i = 2; i < numSegments; i++)
386 tempx = c * dx - s * dy;
387 dy = s * dx + c * dy;
399 static void Ellipse(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float rx,
float ry,
float degrees, SDL_Color color)
401 float thickness = GetLineThickness(renderer);
404 float t = thickness/2;
405 float rot_x = cos(degrees*
M_PI/180);
406 float rot_y = sin(degrees*
M_PI/180);
407 float inner_radius_x = rx - t;
408 float outer_radius_x = rx + t;
409 float inner_radius_y = ry - t;
410 float outer_radius_y = ry + t;
411 float dt = (1.25f/sqrtf(outer_radius_x > outer_radius_y? outer_radius_x : outer_radius_y));
412 int numSegments = 2*
M_PI/dt+1;
417 float inner_trans_x, inner_trans_y;
418 float outer_trans_x, outer_trans_y;
420 BEGIN_UNTEXTURED(
"GPU_Ellipse", GL_TRIANGLES, 2*(numSegments), 6*(numSegments));
422 if(inner_radius_x < 0.0f)
423 inner_radius_x = 0.0f;
424 if(inner_radius_y < 0.0f)
425 inner_radius_y = 0.0f;
430 inner_trans_x = rot_x * inner_radius_x*dx - rot_y * inner_radius_y*dy;
431 inner_trans_y = rot_y * inner_radius_x*dx + rot_x * inner_radius_y*dy;
432 outer_trans_x = rot_x * outer_radius_x*dx - rot_y * outer_radius_y*dy;
433 outer_trans_y = rot_y * outer_radius_x*dx + rot_x * outer_radius_y*dy;
436 for(i = 1; i < numSegments; i++)
438 tempx = c * dx - s * dy;
439 dy = (s * dx + c * dy);
442 inner_trans_x = rot_x * inner_radius_x*dx - rot_y * inner_radius_y*dy;
443 inner_trans_y = rot_y * inner_radius_x*dx + rot_x * inner_radius_y*dy;
444 outer_trans_x = rot_x * outer_radius_x*dx - rot_y * outer_radius_y*dy;
445 outer_trans_y = rot_y * outer_radius_x*dx + rot_x * outer_radius_y*dy;
452 static void EllipseFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float rx,
float ry,
float degrees, SDL_Color color)
456 float rot_x = cos(degrees*
M_PI/180);
457 float rot_y = sin(degrees*
M_PI/180);
458 float dt = (1.25f/sqrtf(rx > ry? rx : ry));
459 int numSegments = 2*
M_PI/dt+1;
464 float trans_x, trans_y;
466 BEGIN_UNTEXTURED(
"GPU_EllipseFilled", GL_TRIANGLES, 3 + (numSegments-2), 3 + (numSegments-2)*3 + 3);
473 trans_x = rot_x * rx*dx - rot_y * ry*dy;
474 trans_y = rot_y * rx*dx + rot_x * ry*dy;
477 tempx = c * dx - s * dy;
478 dy = s * dx + c * dy;
481 trans_x = rot_x * rx*dx - rot_y * ry*dy;
482 trans_y = rot_y * rx*dx + rot_x * ry*dy;
485 for(i = 2; i < numSegments; i++)
487 tempx = c * dx - s * dy;
488 dy = (s * dx + c * dy);
491 trans_x = rot_x * rx*dx - rot_y * ry*dy;
492 trans_y = rot_y * rx*dx + rot_x * ry*dy;
504 static void Sector(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float inner_radius,
float outer_radius,
float start_angle,
float end_angle, SDL_Color color)
507 float dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
509 if(inner_radius < 0.0f)
511 if(outer_radius < 0.0f)
514 if(inner_radius > outer_radius)
516 float s = inner_radius;
517 inner_radius = outer_radius;
521 if(start_angle > end_angle)
523 float swapa = end_angle;
524 end_angle = start_angle;
527 if(start_angle == end_angle)
530 if(inner_radius == outer_radius)
532 Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
536 circled = (end_angle - start_angle >= 360);
538 Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
542 dx1 = inner_radius*cos(end_angle*
RADPERDEG);
543 dy1 = inner_radius*sin(end_angle*RADPERDEG);
544 dx2 = outer_radius*cos(end_angle*RADPERDEG);
545 dy2 = outer_radius*sin(end_angle*RADPERDEG);
546 Line(renderer, target, x+dx1, y+dy1, x+dx2, y+dy2, color);
549 Arc(renderer, target, x, y, outer_radius, start_angle, end_angle, color);
553 dx3 = inner_radius*cos(start_angle*
RADPERDEG);
554 dy3 = inner_radius*sin(start_angle*RADPERDEG);
555 dx4 = outer_radius*cos(start_angle*RADPERDEG);
556 dy4 = outer_radius*sin(start_angle*RADPERDEG);
557 Line(renderer, target, x+dx3, y+dy3, x+dx4, y+dy4, color);
561 static void SectorFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x,
float y,
float inner_radius,
float outer_radius,
float start_angle,
float end_angle, SDL_Color color)
569 if(inner_radius < 0.0f)
571 if(outer_radius < 0.0f)
574 if(inner_radius > outer_radius)
576 float s = inner_radius;
577 inner_radius = outer_radius;
581 if(inner_radius == outer_radius)
583 Arc(renderer, target, x, y, inner_radius, start_angle, end_angle, color);
588 if(start_angle > end_angle)
590 float swapa = end_angle;
591 end_angle = start_angle;
594 if(start_angle == end_angle)
597 if(end_angle - start_angle >= 360)
598 end_angle = start_angle + 360;
602 dt = ((end_angle - start_angle)/360)*(1.25f/sqrtf(outer_radius)) *
DEGPERRAD;
604 numSegments = fabs(end_angle - start_angle)/dt;
611 BEGIN_UNTEXTURED(
"GPU_SectorFilled", GL_TRIANGLES, 3 + (numSegments - 1) + 1, 3 + (numSegments - 1) * 3 + 3);
617 dy = inner_radius*sin(t*RADPERDEG);
620 dx = outer_radius*cos(t*RADPERDEG);
621 dy = outer_radius*sin(t*RADPERDEG);
624 dx = inner_radius*cos(t*RADPERDEG);
625 dy = inner_radius*sin(t*RADPERDEG);
629 for (i = 2; i < numSegments + 1; i++)
635 dx = inner_radius*cos(t*RADPERDEG);
636 dy = inner_radius*sin(t*RADPERDEG);
640 dx = outer_radius*cos(t*RADPERDEG);
641 dy = outer_radius*sin(t*RADPERDEG);
645 use_inner = !use_inner;
652 dx = inner_radius*cos(t*RADPERDEG);
653 dy = inner_radius*sin(t*RADPERDEG);
657 dx = outer_radius*cos(t*RADPERDEG);
658 dy = outer_radius*sin(t*RADPERDEG);
663 use_inner = !use_inner;
668 dx = inner_radius*cos(t*RADPERDEG);
669 dy = inner_radius*sin(t*RADPERDEG);
673 dx = outer_radius*cos(t*RADPERDEG);
674 dy = outer_radius*sin(t*RADPERDEG);
682 static void Tri(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3, SDL_Color color)
696 static void TriFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2,
float x3,
float y3, SDL_Color color)
705 static void Rectangle(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2, SDL_Color color)
721 float thickness = GetLineThickness(renderer);
724 float outer = thickness / 2;
725 float inner_x = outer;
726 float inner_y = outer;
733 if(x1 + inner_x > x2 - inner_x)
734 inner_x = (x2 - x1)/2;
735 if(y1 + inner_y > y2 - inner_y)
736 inner_y = (y2 - y1)/2;
773 static void RectangleFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2, SDL_Color color)
786 #define INCREMENT_CIRCLE \ 787 tempx = c * dx - s * dy; \ 788 dy = s * dx + c * dy; \ 792 static void RectangleRound(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2,
float radius, SDL_Color color)
807 if(radius > (x2-x1)/2)
809 if(radius > (y2-y1)/2)
810 radius = (y2 - y1) / 2;
818 float thickness = GetLineThickness(renderer);
821 float t = thickness/2;
822 float inner_radius = radius - t;
823 float outer_radius = radius + t;
824 float dt = (1.25f/sqrtf(outer_radius));
825 int numSegments = 2*
M_PI/dt+1;
830 numSegments += numSegments % 4;
832 dt = 2*
M_PI/(numSegments-1);
836 int go_to_second = numSegments / 4;
837 int go_to_third = numSegments / 2;
838 int go_to_fourth = 3*numSegments / 4;
845 BEGIN_UNTEXTURED(
"GPU_RectangleRound", GL_TRIANGLES, 2*(numSegments + 4), 6*(numSegments + 4));
847 if(inner_radius < 0.0f)
856 while(i < go_to_second-1)
860 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
868 while(i < go_to_third-1)
872 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
880 while(i < go_to_fourth-1)
884 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
892 while(i < numSegments-1)
896 SET_UNTEXTURED_SEGMENTS(x+inner_radius*dx, y+inner_radius*dy, x+outer_radius*dx, y+outer_radius*dy, r, g, b, a);
905 static void RectangleRoundFilled(
GPU_Renderer* renderer,
GPU_Target* target,
float x1,
float y1,
float x2,
float y2,
float radius, SDL_Color color)
920 if(radius > (x2-x1)/2)
922 if(radius > (y2-y1)/2)
923 radius = (y2 - y1) / 2;
926 float tau = 2 *
M_PI;
928 int verts_per_corner = 7;
929 float corner_angle_increment = (tau / 4) / (verts_per_corner - 1);
932 float angle = tau*0.75f;
936 BEGIN_UNTEXTURED(
"GPU_RectangleRoundFilled", GL_TRIANGLES, 6 + 4 * (verts_per_corner - 1) - 1, 15 + 4 * (verts_per_corner - 1) * 3 - 3);
942 angle += corner_angle_increment;
944 angle += corner_angle_increment;
946 for (i = 2; i < verts_per_corner; i++)
951 angle += corner_angle_increment;
957 for (i = 1; i < verts_per_corner; i++)
962 angle += corner_angle_increment;
968 for (i = 1; i < verts_per_corner; i++)
973 angle += corner_angle_increment;
979 for (i = 1; i < verts_per_corner; i++)
984 angle += corner_angle_increment;
994 static void Polygon(
GPU_Renderer* renderer,
GPU_Target* target,
unsigned int num_vertices,
float* vertices, SDL_Color color)
1000 int numSegments = 2 * num_vertices;
1007 for (i = 2; i < numSegments; i += 2)
1017 static void PolygonFilled(
GPU_Renderer* renderer,
GPU_Target* target,
unsigned int num_vertices,
float* vertices, SDL_Color color)
1019 if(num_vertices < 3)
1023 int numSegments = 2 * num_vertices;
1026 BEGIN_UNTEXTURED(
"GPU_PolygonFilled", GL_TRIANGLES, num_vertices, 3 + (num_vertices - 3) * 3);
1033 if (num_vertices > 3)
1038 for (i = 6; i < numSegments; i += 2)
#define END_UNTEXTURED_SEGMENTS(x1, y1, x2, y2, r, g, b, a)
GPU_Target * current_context_target
#define SET_INDEXED_VERTEX(offset)
#define BEGIN_UNTEXTURED_SEGMENTS(x1, y1, x2, y2, r, g, b, a)
#define SET_UNTEXTURED_SEGMENTS(x1, y1, x2, y2, r, g, b, a)
struct GPU_RendererImpl * impl
#define LOOP_UNTEXTURED_SEGMENTS()
#define SET_UNTEXTURED_VERTEX(x, y, r, g, b, a)
#define BEGIN_UNTEXTURED(function_name, shape, num_additional_vertices, num_additional_indices)