[LAMW] Put one pixel via CanvasSE2 like a pro 😎 lazarus / 43-Android ---------------------------------------------------------------------- José Hernández · 2025-08-28 05:12 Hello everyone, when I need to work with graphics, I use a screen buffer. But I didn't find any procedure or function in Laz_And_GLESv2_Canvas Library could help me to do it. So this situation made me to make one. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TAndroidModule1.DeployBufferToTexture(Buffer: PDWord; W, H,  IdxTexture: Integer);begin  glDisable(GL_DEPTH_BUFFER_BIT);  glBindTexture  (GL_TEXTURE_2D, CanvasES21.Textures[IdxTexture].ID);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  glTexparameteri(GL_Texture_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  glTexparameteri(GL_Texture_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, W, H, 0, GL_RGBA, GL_UNSIGNED_BYTE, Buffer);end;   Why do I prefer using a screen buffer instead of using library functions? 1. I have more control so I can do more things, my only limit is my imagination. 2. Most of the time my own functions are faster than the library's. 3. Computer graphics algorithms are based on memory access: Bresenham's line and circle, filling algorithms, etc. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit unit1; {$mode delphi} interface uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, AndroidWidget  , Laz_And_GLESv2_Canvas, Laz_And_GLESv2_Canvas_h;  type   { TAndroidModule1 }   TAndroidModule1 = class(jForm)    CanvasES21: jCanvasES2;    procedure AndroidModule1JNIPrompt(Sender: TObject);    procedure CanvasES21GLCreate(Sender: TObject);    procedure CanvasES21GLDraw(Sender: TObject);  private    {private declarations}  public    {public declarations}    procedure DeployBufferToTexture(Buffer: PDWord; W, H, IdxTexture: Integer);    procedure DrawTexture(IdxTexture: Integer; x1, y1, x0, y0, Alpha: Single);  end;   { TMyOwnPrimitives }   TMyOwnPrimitives = class      private           Data:            PDWord;           Len:           Integer;           PencilColor:     DWord;           BackgroundColor: DWord;           W,H,X:           Integer;           HalfWidth:       Integer;           HalfHeight:      Integer;        public           constructor Create;           procedure UpdateDimensions(Width, Height: Integer);           procedure SetTheBufferUp;           procedure SetPencilColor(NewColor: DWord);           function  GetWidth:  Integer;           function  GetHeight: Integer;           function  GetBuffer: PDWord;            procedure DrawChessBoard;         procedure DrawTwoChessBoardLine;           procedure DrawChessBoardLine;           procedure DrawTwoChessBoardSquare;         procedure MoveToInitialPoint;           procedure TakeAStep;         procedure TakeAStepBack;           procedure TakeTwoSteps;         procedure Clean;      end; var  AndroidModule1: TAndroidModule1;  SetOfPrimiteves: TMyOwnPrimitives; const   BlackColor   = $ff000000;   RedColor     = $ff0000bf;   GreenColor   = $ff00bf00;   BlueColor    = $ffbf0000;   WhiteColor   = $ffbfbfbf;   Z_COORDINATE_AT_THE_ORIGIN = 0;   FULLY_OPAQUE =  1.0;   RIGHT_CORNER =  1.0;   LEFT_CORNER  = -1.0;   TOP_CORNER   =  1.0;   DOWN_CORNER  = -1.0;  implementation  {$R *.lfm}     { TAndroidModule1 } procedure TAndroidModule1.AndroidModule1JNIPrompt(Sender: TObject);begin  SetOfPrimiteves:= TMyOwnPrimitives.Create;  SetOfPrimiteves.UpdateDimensions(CanvasES21.GetWidth, CanvasES21.GetHeight);  SetOfPrimiteves.SetTheBufferUp;end; procedure TAndroidModule1.CanvasES21GLCreate(Sender: TObject);begin  CanvasES21.Shader_Compile('simon_Vert', 'simon_Frag');  CanvasES21.Shader_Link;  CanvasES21.TexturesCount:=1;   glGenTextures(1, @CanvasES21.Textures[0].ID);end; procedure TAndroidModule1.CanvasES21GLDraw(Sender: TObject);begin  CanvasES21.MVP:= cID4x4;  CanvasES21.SetMVP(CanvasES21.MVP);  CanvasES21.Screen_Setup(CanvasES21.GetWidth, CanvasES21.GetHeight);  CanvasES21.Screen_Clear(0, 0, 0, 1);   with SetOfPrimiteves do begin  UpdateDimensions(CanvasES21.GetWidth, CanvasES21.GetHeight);     Clean;    SetPencilColor(BlueColor);    DrawChessBoard;     DeployBufferToTexture(GetBuffer, GetWidth, GetHeight, 0);  end;   DrawTexture(0, RIGHT_CORNER, TOP_CORNER, LEFT_CORNER, DOWN_CORNER, FULLY_OPAQUE);end; (* This procedure should be part of Laz_And_GLESv2_Canvas.   But I don't know why it isn't. 🤷  *)procedure TAndroidModule1.DeployBufferToTexture(Buffer: PDWord; W, H,  IdxTexture: Integer);begin  glDisable      (GL_DEPTH_BUFFER_BIT);  glBindTexture  (GL_TEXTURE_2D, CanvasES21.Textures[IdxTexture].ID);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  glTexparameteri(GL_Texture_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  glTexparameteri(GL_Texture_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  glTexImage2D   (GL_TEXTURE_2D, 0, GL_RGBA, W, H, 0, GL_RGBA, GL_UNSIGNED_BYTE                , Buffer);end; procedure TAndroidModule1.DrawTexture(IdxTexture: Integer; x1, y1, x0, y0,  Alpha: Single);begin  CanvasES21.DrawTexture(  CanvasES21.Textures[IdxTexture]                         , _xy4CW(x1,y0, x0,y0, x0,y1, x1,y1)                         , Z_COORDINATE_AT_THE_ORIGIN, Alpha);end; { TMyOwnPrimitives }constructor TMyOwnPrimitives.Create;begin  Data:= Nil; Len:=0; W:= 0; H:=0; X:=0;  HalfWidth:= 0;  HalfHeight:= 0;  PencilColor:= WhiteColor;  BackgroundColor:= BlackColor;end; procedure TMyOwnPrimitives.UpdateDimensions(Width, Height: Integer);begin  W:= Width; H:= Height;  HalfWidth:= Width shr 1;  HalfHeight:= Height shr 1;end; procedure TMyOwnPrimitives.SetTheBufferUp;begin  Len:= W*H;  GetMem(Data, Len*SizeOf(DWord));end; function TMyOwnPrimitives.GetWidth: Integer;begin  Result:= W;end; function TMyOwnPrimitives.GetHeight: Integer;begin  Result:= H;end; function TMyOwnPrimitives.GetBuffer: PDWord;begin  Result:= Data;end; procedure TMyOwnPrimitives.SetPencilColor(NewColor: DWord);begin  PencilColor:= NewColor;end; procedure TMyOwnPrimitives.DrawChessBoard;var i: Integer;begin  MoveToInitialPoint;  for i:= 1 to HalfHeight do DrawTwoChessBoardLine;end; procedure TMyOwnPrimitives.DrawTwoChessBoardLine;begin  DrawChessBoardLine;  TakeAStep;  DrawChessBoardLine;  TakeAStepBack;end; procedure TMyOwnPrimitives.DrawChessBoardLine;var i: Integer;begin  for i:= 1 to HalfWidth do DrawTwoChessBoardSquare;end; procedure TMyOwnPrimitives.DrawTwoChessBoardSquare;begin  Data[X]:= PencilColor;  TakeTwoSteps;end; procedure TMyOwnPrimitives.MoveToInitialPoint;begin  X:= 0;end; procedure TMyOwnPrimitives.TakeAStep;begin  Inc(X);end; procedure TMyOwnPrimitives.TakeAStepBack;begin  Dec(X);end; procedure TMyOwnPrimitives.TakeTwoSteps;begin  Inc(X, 2);end; procedure TMyOwnPrimitives.Clean;begin  FillDWord(Data^, Len, BackgroundColor);end; end.   This Code makes a Chess Board pixel by pixel. This confirms that the Screen buffer is working.  Check the images: