source: trunk/Methods/UMethodOpenGLPBO.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 6.1 KB
Line 
1unit UMethodOpenGLPBO;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UDrawMethod, UFastBitmap, Controls, Graphics
9 {$IFDEF OPENGL}, GL, GLExt, OpenGLContext{$ENDIF};
10
11{$IFDEF OPENGL}
12type
13 { TMethodOpenGLPBO }
14
15 TMethodOpenGLPBO = class(TDrawMethodOpenGL)
16 pboIds: array[0..1] of GLuint;
17 Index, NextIndex: Integer;
18 procedure Init(AParent: TWinControl; Size: TPoint; PixelFormat: TPixelFormat); override;
19 constructor Create; override;
20 destructor Destroy; override;
21 procedure DrawFrame(FastBitmap: TFastBitmap); override;
22 end;
23 {$ENDIF}
24
25
26implementation
27
28{$IFDEF OPENGL}
29{ TMethodOpenGLPBO }
30
31//procedure glGenBuffersARB2 : procedure(n : GLsizei; buffers : PGLuint); extdecl;
32
33procedure TMethodOpenGLPBO.Init(AParent: TWinControl; Size: TPoint; PixelFormat: TPixelFormat);
34var
35 DataSize: Integer;
36 glExtensions: string;
37begin
38 inherited;
39
40 OpenGLControl.MakeCurrent;
41 DataSize := OpenGLControl.Width * OpenGLControl.Height * SizeOf(Integer);
42// glGenBuffersARB(Length(pboIds), PGLuint(pboIds));
43 //if glext_LoadExtension('GL_ARB_pixel_buffer_object') then
44 if Load_GL_ARB_vertex_buffer_object then begin
45 glGenBuffersARB(2, @pboIds);
46 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[0]);
47 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, DataSize, Pointer(0), GL_STREAM_READ_ARB);
48 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboIds[1]);
49 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, DataSize, Pointer(0), GL_STREAM_READ_ARB);
50
51 end else raise Exception.Create('GL_ARB_pixel_buffer_object not supported');
52
53 glEnable(GL_TEXTURE_2D);
54 glBindTexture(GL_TEXTURE_2D, TextureId);
55 //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
56 //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
57 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
58 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
59 glTexImage2D(GL_TEXTURE_2D, 0, 4, OpenGLControl.Width, OpenGLControl.Height,
60 0, GL_RGBA, GL_UNSIGNED_BYTE, OpenGLBitmap);
61end;
62
63constructor TMethodOpenGLPBO.Create;
64begin
65 inherited Create;
66 Caption := 'OpenGL PBO';
67 PaintObject := poOpenGL;
68// SetLength(pboIds, 2);
69 Index := 0;
70 NextIndex := 1;
71 Description.Add('This method use OpenGL acceleration same like other OpenGL method but ' +
72 'use DMA(Direct Memory Access) for faster texture data transfer without use of CPU.');
73end;
74
75destructor TMethodOpenGLPBO.Destroy;
76begin
77 inherited Destroy;
78end;
79
80procedure TMethodOpenGLPBO.DrawFrame(FastBitmap: TFastBitmap);
81var
82 X, Y: Integer;
83 P: PCardinal;
84 R: PCardinal;
85 Ptr: ^GLubyte;
86 TextureShift: TPoint;
87 TextureShift2: TPoint;
88const
89 GL_CLAMP_TO_EDGE = $812F;
90begin
91 // "index" is used to read pixels from framebuffer to a PBO
92 // "nextIndex" is used to update pixels in the other PBO
93 Index := (Index + 1) mod 2;
94 NextIndex := (Index + 1) mod 2;
95
96 glLoadIdentity;
97
98 glBindTexture(GL_TEXTURE_2D, TextureId);
99 //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
100 //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
101 //glTexImage2D(GL_TEXTURE_2D, 0, 4, OpenGLControl.Width, OpenGLControl.Height,
102 // 0, GL_RGBA, GL_UNSIGNED_BYTE, OpenGLBitmap);
103 //glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 256,
104 //0, GL_RGBA, GL_UNSIGNED_BYTE, OpenGLBitmap);
105
106 // bind the texture and PBO
107 //glBindTexture(GL_TEXTURE_2D, textureId);
108 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);
109
110 // copy pixels from PBO to texture object
111 // Use offset instead of ponter.
112 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, OpenGLControl.Width, OpenGLControl.Height,
113 GL_BGRA, GL_UNSIGNED_BYTE, Pointer(0));
114
115
116 // bind PBO to update texture source
117 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[nextIndex]);
118
119 // Note that glMapBufferARB() causes sync issue.
120 // If GPU is working with this buffer, glMapBufferARB() will wait(stall)
121 // until GPU to finish its job. To avoid waiting (idle), you can call
122 // first glBufferDataARB() with NULL pointer before glMapBufferARB().
123 // If you do that, the previous data in PBO will be discarded and
124 // glMapBufferARB() returns a new allocated pointer immediately
125 // even if GPU is still working with the previous data.
126 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, OpenGLControl.Width * OpenGLControl.Height * SizeOf(Integer), Pointer(0), GL_STREAM_DRAW_ARB);
127
128 // map the buffer object into client's memory
129 ptr := glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
130 if Assigned(ptr) then begin
131 // update data directly on the mapped buffer
132 P := PCardinal(Ptr);
133 with FastBitmap do
134 for Y := 0 to Size.Y - 2 do begin
135 R := P;
136 for X := 0 to Size.X - 1 do begin
137 R^ := NoSwapBRComponent(Pixels[X, Y]) or $ff000000;
138 Inc(R);
139 end;
140 Inc(P, Size.X);
141 end;
142 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
143 end;
144
145 // it is good idea to release PBOs with ID 0 after use.
146 // Once bound with 0, all pixel operations are back to normal ways.
147 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
148
149 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
150 //glRotatef(30.0, 0, 0, 1.0);
151 glTranslatef(-OpenGLControl.Width / 2, -OpenGLControl.Height / 2, 0.0);
152 glBindTexture(GL_TEXTURE_2D, TextureId);
153
154 TextureShift := Point(0, 0);
155 TextureShift2 := Point(0, 0);
156 glBegin(GL_QUADS);
157 glColor3ub(255, 255, 255);
158 glTexCoord2f(TextureShift.X, TextureShift.Y);
159 glVertex3f(TextureShift2.X, TextureShift2.Y, 0);
160 glTexCoord2f(TextureShift.X + OpenGLControl.Width div 2, TextureShift.Y);
161 glVertex3f(TextureShift2.X + OpenGLControl.Width, TextureShift2.Y, 0);
162 glTexCoord2f(TextureShift.X + OpenGLControl.Width div 2, TextureShift.Y + OpenGLControl.Height div 2);
163 glVertex3f(TextureShift2.X + OpenGLControl.Width, TextureShift2.Y + OpenGLControl.Height, 0);
164 glTexCoord2f(TextureShift.X, TextureShift.Y + OpenGLControl.Height div 2);
165 glVertex3f(TextureShift2.X, TextureShift2.Y + OpenGLControl.Height, 0);
166 glEnd();
167
168 OpenGLControl.SwapBuffers;
169end;
170
171{$ENDIF}
172
173end.
174
Note: See TracBrowser for help on using the repository browser.