3 uses Allegro, Math, SDL2, e_Log;
6 GL_INVALID_ENUM = $0500;
10 ValPerColor = 1; (* colors stored in one integer *)
15 TArrayFloat = array of GLfloat;
16 TArrayInteger = array of Integer;
25 TArrayTexture = array of record
36 stack: array [0..StackSize - 1] of record
44 function AddTexture: Integer;
47 for i := 1 to High(tex) do
48 if not tex[i].used then
56 SetLength(tex, i + 1);
62 procedure RemoveTexture(i: Integer);
65 assert(i <= High(tex));
66 assert((i = 0) or tex[i].used); (* free unallocated texture *)
68 if tex[i].bmp <> nil then
69 destroy_bitmap(tex[i].bmp);
73 procedure Addi (var x: TArrayInteger; f: Integer);
81 procedure Addf (var x: TArrayFloat; f: GLfloat);
91 procedure glEnable(cap: GLenum);
95 procedure glDisable(cap: GLenum);
99 function glIsEnabled(cap: GLenum): GLboolean;
104 function glGetString(name: GLenum): PChar;
106 if name = GL_EXTENSIONS then (* separated by space *)
107 result := 'GL_ARB_texture_non_power_of_two'
112 procedure glClearColor(red, green, blue, alpha: GLclampf);
114 clearColor := makeacol(floor(red * 255), floor(green * 255), floor(blue * 255), floor(alpha * 255));
117 procedure glClear(mask: GLbitfield);
119 if (mask and GL_COLOR_BUFFER_BIT) <> 0 then
120 clear_to_color(sdl2allegro_screen, clearColor)
123 procedure glAlphaFunc(func: GLenum; ref: GLclampf);
127 procedure glBlendFunc(sfactor, dfactor: GLenum);
131 procedure glPointSize(size: GLfloat);
134 if size <= 1.0 then pointSize := ceil(size)
135 else pointSize := floor(size)
138 procedure glLineWidth(width: GLfloat);
140 (* width > 1 used in rare cases, not critical *)
143 procedure glGetIntegerv(pname: GLenum; params: PGLint);
156 procedure glBegin(mode: GLenum);
158 assert(cmds.mode = GL_INVALID_ENUM);
159 assert((mode = GL_POINTS) or (mode = GL_LINES) or (mode = GL_QUADS));
161 SetLength(cmds.v, 0);
162 SetLength(cmds.c, 0);
163 SetLength(cmds.t, 0);
168 i, j, k, w, h, x0, y0, x1, y1, offx, offy, tmp, s0, t0, s1, t1: Integer;
169 oldx0, oldy0, oldx1, oldy1: cint;
170 flipv, fliph: Boolean;
171 draw_sprite_proc: procedure (bmp, sprite: Allegro.PBITMAP; x, y: cint); cdecl;
173 assert(cmds.mode <> GL_INVALID_ENUM);
174 assert(Length(cmds.v) mod ValPerVertex = 0);
175 assert(Length(cmds.c) mod ValPerColor = 0);
176 assert(Length(cmds.t) mod ValPerCoord = 0);
178 offx := vpx + stack[stack_ptr].x;
179 offy := vpy + stack[stack_ptr].y;
184 (* implement case for texture coords? *)
185 if pointSize = 1 then
187 if Length(cmds.c) <> 0 then
189 assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *)
190 for i := 0 to Length(cmds.v) div 2 - 1 do
191 putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], cmds.c[i])
195 for i := 0 to Length(cmds.v) div 2 - 1 do
196 putpixel(sdl2allegro_screen, offx + cmds.v[i * 2], offy + cmds.v[i * 2 + 1], ccol)
199 else if pointSize > 1 then
201 x0 := offx - pointSize div 2;
202 y0 := offy - pointSize div 2;
203 x1 := offx - (pointSize - 1) div 2;
204 y1 := offy - (pointSize - 1) div 2;
205 if Length(cmds.c) <> 0 then
207 assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *)
208 for i := 0 to Length(cmds.v) div 2 - 1 do
210 w := cmds.v[i * 2 + 0];
211 h := cmds.v[i * 2 + 1];
212 rectfill(sdl2allegro_screen, x0 + w, y0 + h, x1 + w, y1 + h, cmds.c[i])
217 for i := 0 to Length(cmds.v) div 2 - 1 do
219 w := cmds.v[i * 2 + 0];
220 h := cmds.v[i * 2 + 1];
221 rectfill(sdl2allegro_screen, x0 + w, y0 + h, x1 + w, y1 + h, ccol)
228 assert(Length(cmds.v) mod 4 = 0); (* broken line *)
229 (* implement case for texture coords? *)
230 if Length(cmds.c) <> 0 then
232 assert(Length(cmds.c) * 2 = Length(cmds.v));
233 for i := 0 to Length(cmds.v) div 4 - 1 do
234 fastline(sdl2allegro_screen, offx + cmds.v[i * 4], offy + cmds.v[i * 4 + 1], offx + cmds.v[i * 4 + 2], offy + cmds.v[i * 4 + 3], cmds.c[i * 2])
238 for i := 0 to Length(cmds.v) div 4 - 1 do
239 fastline(sdl2allegro_screen, offx + cmds.v[i * 4], offy + cmds.v[i * 4 + 1], offx + cmds.v[i * 4 + 2], offy + cmds.v[i * 4 + 3], ccol)
244 ASSERT(Length(cmds.v) mod 8 = 0); (* broken quad *)
245 if Length(cmds.t) <> 0 then
247 ASSERT(Length(cmds.t) = Length(cmds.v)); (* not enough texture coords *)
249 ASSERT(ctex <= High(tex));
250 ASSERT(tex[ctex].bmp <> nil);
251 for i := 0 to Length(cmds.v) div 8 - 1 do
253 flipv := False; fliph := False;
254 x0 := cmds.v[i * 8 + 0]; y0 := cmds.v[i * 8 + 1];
255 x1 := cmds.v[i * 8 + 4]; y1 := cmds.v[i * 8 + 5];
271 w := tex[ctex].bmp.w;
272 h := tex[ctex].bmp.h;
273 s0 := Trunc(cmds.t[i * 8 + 0] * w);
274 t0 := Trunc(cmds.t[i * 8 + 1] * h);
275 s1 := Trunc(cmds.t[i * 8 + 4] * w);
276 t1 := Trunc(cmds.t[i * 8 + 5] * h);
311 if flipv and fliph then
312 draw_sprite_proc := Allegro.draw_sprite_vh_flip
314 draw_sprite_proc := Allegro.draw_sprite_v_flip
316 draw_sprite_proc := Allegro.draw_sprite_h_flip
318 draw_sprite_proc := Allegro.draw_sprite;
320 oldx0 := 0; oldy0 := 0; oldx1 := 0; oldy1 := 0;
321 get_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1);
322 set_clip_rect(sdl2allegro_screen, max(oldx0, offx + x0), max(oldy0, offy + y0), min(oldx1, offx + x1), min(oldy1, offy + y1));
324 for j := 0 to (y1 - y0 + h - 1) div h - 1 do
325 for k := 0 to (x1 - x0 + w - 1) div w - 1 do
326 draw_sprite_proc(sdl2allegro_screen, tex[ctex].bmp, offx + x0 + k * w - s0, offy + y0 + j * h - t0);
328 set_clip_rect(sdl2allegro_screen, oldx0, oldy0, oldx1, oldy1);
330 //rect(sdl2allegro_screen, offx + x0, offy + y0, offx + x1, offy + y1, makecol(255, 0, 0));
331 //rect(sdl2allegro_screen, offx + oldx0, offy + oldy0, offx + oldx1, offy + oldx1, makecol(0, 255, 0));
334 else if Length(cmds.c) <> 0 then
336 assert(Length(cmds.c) * 2 = Length(cmds.v)); (* not enough colors *)
337 for i := 0 to Length(cmds.v) div 8 - 1 do
338 rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], cmds.c[i * 4])
342 for i := 0 to Length(cmds.v) div 8 - 1 do
343 rectfill(sdl2allegro_screen, offx + cmds.v[i * 8], offy + cmds.v[i * 8 + 1], offx + cmds.v[i * 8 + 4], offy + cmds.v[i * 8 + 5], ccol)
350 SetLength(cmds.v, 0);
351 SetLength(cmds.c, 0);
352 SetLength(cmds.t, 0);
353 cmds.mode := GL_INVALID_ENUM;
356 procedure glVertex2f(x, y: GLfloat);
358 Addi(cmds.v, ceil(x));
359 Addi(cmds.v, ceil(y))
362 procedure glVertex2i(x, y: GLint);
368 procedure glColor4f(red, green, blue, alpha: GLfloat);
370 ccol := makeacol(floor(red * 255), floor(green * 255), floor(blue * 255), floor(alpha * 255));
374 procedure glColor4ub(red, green, blue, alpha: GLubyte);
376 ccol := makeacol(red, green, blue, alpha);
380 procedure glColor3ub(red, green, blue: GLubyte);
382 ccol := makecol(red, green, blue);
386 procedure glTexCoord2f(s, t: GLfloat);
392 procedure glTexCoord2i(s, t: GLint);
398 procedure glReadPixels(x, y: GLint; width, height: GLsizei; format, atype: GLenum; pixels: Pointer);
402 procedure glLoadIdentity;
404 if matrixMode <> GL_MODELVIEW then Exit;
405 with stack[stack_ptr] do
409 (* TODO Rotation and scale *)
413 procedure glMatrixMode(mode: GLenum);
415 (* GL_PROJECTION -> verify or ignore *)
416 (* GL_MODELVIEW -> apply *)
417 ASSERT((mode = GL_PROJECTION) or (mode = GL_MODELVIEW));
421 procedure glLoadMatrixd(const m: PGLdouble);
423 if matrixMode <> GL_MODELVIEW then Exit;
426 e_LogWritefln('glLoadMatrix:', []);
427 e_LogWritefln('| %s %s %s %s |', [m[0], m[1], m[2], m[3]]);
428 e_LogWritefln('| %s %s %s %s |', [m[4], m[5], m[6], m[7]]);
429 e_LogWritefln('| %s %s %s %s |', [m[8], m[9], m[10], m[11]]);
430 e_LogWritefln('| %s %s %s %s |', [m[12], m[13], m[14], m[15]]);
432 with stack[stack_ptr] do
437 (* TODO Rotation and Scale *)
441 procedure glPushMatrix;
443 if matrixMode <> GL_MODELVIEW then Exit;
444 stack[stack_ptr + 1] := stack[stack_ptr];
448 procedure glPopMatrix;
450 if matrixMode <> GL_MODELVIEW then Exit;
454 procedure glTranslatef(x, y, z: GLfloat);
456 if matrixMode <> GL_MODELVIEW then Exit;
457 ASSERT(z = 0); (* 3D not supported *)
458 stack[stack_ptr].x += Trunc(x);
459 stack[stack_ptr].y += Trunc(y);
462 procedure glRotatef(angle, x, y, z: GLfloat);
464 if matrixMode <> GL_MODELVIEW then Exit;
465 ASSERT(x = 0); (* 3D not supported *)
466 ASSERT(y = 0); (* 3D not supported *)
467 (* TODO a := deg(angle * z) *)
470 procedure glScalef(x, y, z: GLfloat);
472 if matrixMode <> GL_MODELVIEW then Exit;
473 (* 3D not supported, but z can be any *)
477 procedure glViewport(x, y: GLint; width, height: GLsizei);
480 set_clip_rect(sdl2allegro_screen, x, y, x + width, y + height);
483 procedure glScissor(x, y: GLint; width, height: GLsizei);
485 //set_clip_rect(sdl2allegro_screen, x, y, width, height)
488 procedure glStencilMask(mask: GLuint);
492 procedure glStencilFunc(func: GLenum; ref: GLint; mask: GLuint);
496 procedure glStencilOp(fail, zfail, zpass: GLenum);
500 procedure glColorMask(red, green, blue, alpha: GLboolean);
504 procedure glBindTexture(target: GLenum; texture: GLuint);
506 assert(target = GL_TEXTURE_2D);
510 procedure glGenTextures(n: GLsizei; textures: PGLuint);
513 for i := 0 to n - 1 do
514 textures[i] := AddTexture
517 procedure glTexEnvi(target: GLenum; pname: GLenum; param: GLint);
521 procedure glTexParameterf(target: GLenum; pname: GLenum; param: GLfloat);
525 procedure glTexParameteri(target: GLenum; pname: GLenum; param: GLint);
529 procedure glTexImage2D(target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer);
530 var i, j, adr: Integer; p: PByte; color, trans: cint;
532 assert(target = GL_TEXTURE_2D);
534 assert((internalformat = GL_RGBA) or (internalformat = GL_RGB));
535 assert((format = GL_RGBA) or (format = GL_RGB));
537 assert(atype = GL_UNSIGNED_BYTE);
540 assert(ctex <= High(tex));
541 assert(tex[ctex].used);
543 if tex[ctex].bmp <> nil then
544 destroy_bitmap(tex[ctex].bmp);
545 tex[ctex].bmp := create_system_bitmap(width, height);
546 if tex[ctex].bmp = nil then
547 tex[ctex].bmp := create_bitmap(width, height);
548 assert(tex[ctex].bmp <> nil);
550 if pixels = nil then exit;
553 if format = GL_RGBA then
555 if DEFAULT_DEPTH <= 8 then
558 trans := makeacol(255, 0, 255, 0);
560 for j := 0 to height - 1 do
561 for i := 0 to width - 1 do
563 adr := j * width * 4 + i * 4;
564 if p[adr + 3] = 0 then
567 color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]);
568 putpixel(tex[ctex].bmp, i, j, color)
573 for j := 0 to height - 1 do
574 for i := 0 to width - 1 do
576 adr := j * width * 3 + i * 3;
577 putpixel(tex[ctex].bmp, i, j, makecol(p[adr], p[adr + 1], p[adr + 2]))
582 procedure glTexSubImage2D(target: GLenum; level, xoffset, yoffset: GLint; width, height: GLsizei; format, atype: GLenum; const pixels: Pointer);
583 var i, j, adr: Integer; p: PByte; color, trans: Cint;
585 assert(target = GL_TEXTURE_2D);
587 assert((format = GL_RGBA) or (format = GL_RGB));
588 assert(atype = GL_UNSIGNED_BYTE);
591 assert(ctex <= High(tex));
592 assert(tex[ctex].used);
597 if pixels = nil then exit;
600 if format = GL_RGBA then
602 if DEFAULT_DEPTH <= 8 then
605 trans := makeacol(255, 0, 255, 0);
607 for j := 0 to height - 1 do
608 for i := 0 to width - 1 do
610 adr := j * width * 4 + i * 4;
611 if p[adr + 3] = 0 then
614 color := makeacol(p[adr], p[adr + 1], p[adr + 2], p[adr + 3]);
615 putpixel(tex[ctex].bmp, i, j, color)
620 for j := 0 to height - 1 do
621 for i := 0 to width - 1 do
623 adr := j * width * 3 + i * 3;
624 putpixel(tex[ctex].bmp, i, j, makecol(p[adr], p[adr + 1], p[adr + 2]))
629 procedure glDeleteTextures(n: GLsizei; const textures: PGLuint);
632 for i := 0 to n - 1 do
633 RemoveTexture(textures[i])
638 cmds.mode := GL_INVALID_ENUM