1Name 2 3 EXT_pixel_buffer_object 4 5Name Strings 6 7 GL_EXT_pixel_buffer_object 8 9Status 10 11 Implemented by NVIDIA drivers (Release 55). 12 13Contributors 14 15 Ralf Biermann 16 Derek Cornish 17 Matt Craighead 18 Bill Licea-Kane 19 Brian Paul 20 21Contact 22 23 Ralf Biermann, NVIDIA Corporation (rbiermann 'at' nvidia.com) 24 Derek Cornish, NVIDIA Corporation (dcornish 'at' nvidia.com) 25 26IP Status 27 28 Unknown. 29 30Version 31 32 NVIDIA Date: March 29, 2004 (version 1.0) 33 34Number 35 36 302 37 38Status 39 40 NVIDIA Release 55 (early 2004) drivers support this extension. 41 42Dependencies 43 44 Written based on the wording of the OpenGL 1.5 specification. 45 46 GL_NV_pixel_data_range affects the definition of this extension. 47 48Overview 49 50 This extension expands on the interface provided by buffer objects. 51 It is intended to permit buffer objects to be used not only with 52 vertex array data, but also with pixel data. 53 Buffer objects were promoted from the ARB_vertex_buffer_object 54 extension in OpenGL 1.5. 55 56 Recall that buffer objects conceptually are nothing more than arrays 57 of bytes, just like any chunk of memory. Buffer objects allow GL 58 commands to source data from a buffer object by binding the buffer 59 object to a given target and then overloading a certain set of GL 60 commands' pointer arguments to refer to offsets inside the buffer, 61 rather than pointers to user memory. An offset is encoded in a 62 pointer by adding the offset to a null pointer. 63 64 This extension does not add any new functionality to buffer 65 objects themselves. It simply adds two new targets to which buffer 66 objects can be bound: PIXEL_PACK_BUFFER and PIXEL_UNPACK_BUFFER. 67 When a buffer object is bound to the PIXEL_PACK_BUFFER target, 68 commands such as ReadPixels write their data into a buffer object. 69 When a buffer object is bound to the PIXEL_UNPACK_BUFFER target, 70 commands such as DrawPixels read their data from a buffer object. 71 72 There are a wide variety of applications for such functionality. 73 Some of the most interesting ones are: 74 75 - "Render to vertex array." The application can use a fragment 76 program to render some image into one of its buffers, then read 77 this image out into a buffer object via ReadPixels. Then, it can 78 use this buffer object as a source of vertex data. 79 80 - Streaming textures. If the application uses MapBuffer/UnmapBuffer 81 to write its data for TexSubImage into a buffer object, at least 82 one of the data copies usually required to download a texture can 83 be eliminated, significantly increasing texture download 84 performance. 85 86 - Asynchronous ReadPixels. If an application needs to read back a 87 number of images and process them with the CPU, the existing GL 88 interface makes it nearly impossible to pipeline this operation. 89 The driver will typically send the hardware a readback command 90 when ReadPixels is called, and then wait for all of the data to 91 be available before returning control to the application. Then, 92 the application can either process the data immediately or call 93 ReadPixels again; in neither case will the readback overlap with 94 the processing. If the application issues several readbacks into 95 several buffer objects, however, and then maps each one to process 96 its data, then the readbacks can proceed in parallel with the data 97 processing. 98 99Issues 100 101 How does this extension relate to ARB_vertex_buffer_object? 102 103 It builds on the ARB_vertex_buffer_object framework by adding 104 two new targets that buffers can be bound to. 105 106 How does this extension relate to NV_pixel_data_range? 107 108 This extension relates to NV_pixel_data_range in the same way that 109 ARB_vertex_buffer_object relates to NV_vertex_array_range. To 110 paraphrase the ARB_vertex_buffer_object spec, here are the main 111 differences: 112 113 - Applications are no longer responsible for memory management 114 and synchronization. 115 116 - Applications may still access high-performance memory directly, 117 but this is optional, and such access is more restricted. 118 119 - Buffer changes (BindBuffer) are generally expected to 120 be very lightweight, rather than extremely heavyweight 121 (PixelDataRangeNV). 122 123 - A platform-specific allocator such as wgl/glXAllocateMemoryNV 124 is no longer required. 125 126 Can a given buffer be used for both vertex and pixel data? 127 128 RESOLVED: YES. All buffers can be used with all buffer bindings, 129 in whatever combinations the application finds useful. Consider 130 yourself warned, however, by the following issue. 131 132 May implementations make use of the target as a hint to select an 133 appropriate memory space for the buffer? 134 135 RESOLVED: YES, as long as such behavior is transparent to the 136 application. Some implementations may choose, for example, 137 that they would rather stream vertex data from write-combined 138 system memory, element (or index) data from video memory, and 139 pixel data from video memory. 140 141 In fact, one can imagine arbitrarily complicated heuristics for 142 selecting the memory space, based on factors such as the target, 143 the "usage" argument, and the application's observed behavior. 144 145 While it is entirely legal to create a buffer object by binding 146 it to ARRAY_BUFFER and loading it with data, then using it with 147 the PIXEL_UNPACK_BUFFER_EXT or PIXEL_PACK_BUFFER_EXT binding, such 148 behavior is liable to confuse the driver and may hurt performance. 149 If the driver implemented the hypothetical heuristic described 150 earlier, such a buffer might have already been located in 151 write-combined system memory, and so the driver would have to 152 choose between two bad options: relocate the buffer into video 153 memory, or accept lower performance caused by streaming pixel 154 data from slower system memory. 155 156 Should all pixel path commands be supported, or just a subset of 157 them? 158 159 RESOLVED: ALL. While there is little reason to believe that, 160 say, ConvolutionFilter2D would benefit from this extension, there 161 is no reason _not_ to support it. The full list of commands 162 affected by this extension is listed in the spec. 163 164 Should PixelMap and GetPixelMap be supported? 165 166 RESOLVED: YES. They're not really pixel path operations, but, 167 again, there is no good reason to omit operations, and they _are_ 168 operations that pass around big chunks of pixel-related data. 169 If we support PolygonStipple, surely we should support this. 170 171 How does the buffer binding state push/pop? 172 173 RESOLVED: As part of the pixel store client state. This is 174 analogous to how the vertex buffer object bindings pushed/popped 175 as part of the vertex array client state. 176 177 Should NV_pixel_data_range (PDR) be used concurrently with pixel 178 buffer objects ? 179 180 RESOLVED: NO. While it would be possible to allocate a memory 181 range for PDR, using a pointer into this memory range with one 182 of the commands affected by EXT_pixel_buffer_object will not 183 work if a pixel buffer object other than zero is bound to the 184 buffer binding point affecting the command. Pixel buffer objects 185 always have higher precedence than PDR. 186 187 Do the null pointer rules for glTexImage1D, glTexImage2D 188 and glTexImage3D for allocating textures with undefined 189 content also apply when a non-zero buffer object is bound to 190 PIXEL_UNPACK_BUFFER_BINDING_EXT ? 191 192 RESOLVED: NO. The null pointer is interpreted as a non-zero 193 pointer to the data storage whose contents may be still 194 undefined. This data will be used to create the texture array. 195 If the null pointer rule is required, no non-zero buffer object 196 should be bound to PIXEL_UNPACK_BUFFER_BINDING_EXT. 197 198New Procedures and Functions 199 200 None. 201 202New Tokens 203 204 Accepted by the <target> parameters of BindBuffer, BufferData, 205 BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData, 206 GetBufferParameteriv, and GetBufferPointerv: 207 208 PIXEL_PACK_BUFFER_EXT 0x88EB 209 PIXEL_UNPACK_BUFFER_EXT 0x88EC 210 211 Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, 212 GetFloatv, and GetDoublev: 213 214 PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED 215 PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF 216 217 218Additions to Chapter 2 of the GL Specification (OpenGL Operation) 219 220 None 221 222Additions to Chapter 3 of the 1.2.1 Specification (Rasterization) 223 224 Additions to subsection 3.8.1 of the 1.2.1 Specification (Texture 225 Image Specification) 226 227 The extension EXT_pixel_buffer_object makes an exception to this 228 rule of passing a null pointer to glTexImage1D, glTexImage2D and 229 glTexImage3D. If PIXEL_UNPACK_BUFFER_BINDING_EXT is non-zero 230 and a null pointer is passed to these functions, the texture 231 array is created and the image contents are sourced from the 232 data store of the bound buffer object. 233 234Additions to Chapter 4 of the 1.2.1 Specification (Per-Fragment 235Operations and the Frame Buffer) 236 237 Added a subsection 4.3.5 (Pixel Buffer Object unpack operation) 238 in section 4.3 (Drawing, Reading and copying Pixels) 239 240 The extension EXT_pixel_buffer_object affects the operation of 241 several OpenGL commands described in section 3.6 (Pixel Rectangles), 242 section 3.7 (Bitmaps), and section 3.8 (Texturing). 243 244 In unextended OpenGL 1.3 with ARB_imaging support, the commands 245 glBitmap, glColorSubTable, glColorTable, glCompressedTexImage1D, 246 glCompressedTexImage2D, glCompressedTexImage3D, 247 glCompressedTexSubImage1D, glCompressedTexSubImage2D, 248 glCompressedTexSubImage3D, glConvolutionFilter1D, 249 glConvolutionFilter2D, glDrawPixels, glPixelMapfv, glPixelMapuiv, 250 glPixelMapusv, glPolygonStipple, glSeparableFilter2D, glTexImage1D, 251 glTexImage2D, glTexImage3D, glTexSubImage1D, glTexSubImage2D 252 and glTexSubImage3D operate as previously defined, except 253 that pixel data is sourced from a buffer object's data store if 254 PIXEL_UNPACK_BUFFER_BINDING_EXT is non-zero. When the data is sourced 255 from a buffer object, the pointer value passed in as an argument to 256 the command is used to compute an offset, in basic machine units, 257 into the data store of the buffer object. This offset is computed 258 by subtracting a null pointer from the pointer value, where both 259 pointers are treated as pointers to basic machine units. 260 261Additions to Chapter 5 of the 1.2.1 Specification (Special Functions) 262 263 None 264 265Additions to Chapter 6 of the 1.2.1 Specification (State and State 266Requests) 267 268 Additions to subsection 6.1.13 (Buffer Object Queries) in chapter 6 269 270 In unextended OpenGL 1.5 with ARB_imaging support, the commands 271 glGetColorTable, glGetCompressedTexImage, glGetConvolutionFilter, 272 glGetHistogram, glGetMinmax, glGetPixelMapfv, glGetPixelMapuiv, 273 glGetPixelMapusv, glGetPolygonStipple, glGetSeparableFilter, 274 glGetTexImage and glReadPixels operate as previously defined, 275 except that pixel data is stored in a buffer object's data store if 276 PIXEL_PACK_BUFFER_BINDING_EXT is non-zero. When a buffer object is 277 the target of the pixel data, the target pointer value passed in as 278 an argument to the command is used to compute an offset, in basic 279 machine units, into the data store of the buffer object. This offset 280 is computed by subtracting a null pointer from the pointer value, 281 where both pointers are treated as pointers to basic machine units. 282 283Errors 284 285 None 286 287New State 288 289(table 6.20, Pixels, p. 235) 290 291 Get Value Type Get Command Initial Value Sec Attribute 292 --------- ---- ----------- ------------- --- --------- 293 PIXEL_PACK_BUFFER_BINDING_EXT Z+ GetIntegerv 0 4.3.5 pixel-store 294 PIXEL_UNPACK_BUFFER_BINDING_EXT Z+ GetIntegerv 0 6.1.13 pixel-store 295 296New Implementation Dependent State 297 298 (none) 299 300 301Usage Examples 302 303 Convenient macro definition for specifying buffer offsets: 304 305 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) 306 307 Example 1: Render to vertex array 308 309 // create a buffer object for a number of vertices consisting of 310 // 4 float values per vertex 311 GenBuffers(1, vertexBuffer); 312 BindBuffer(PIXEL_PACK_BUFFER_EXT, vertexBuffer); 313 BufferData(PIXEL_PACK_BUFFER_EXT, numberVertices*4, NULL, DYNAMIC_DRAW); 314 315 // render vertex data into framebuffer using a fragment program 316 BindProgramARB(FRAGMENT_PROGRAM_ARB, fragmentProgram); 317 DrawBuffer(GL_BACK); 318 renderVertexData(); 319 BindProgramARB(FRAGMENT_PROGRAM_ARB, 0); 320 321 // read the vertex data back from framebuffer 322 ReadBuffer(GL_BACK); 323 ReadPixels(0, 0, numberVertices*4, height/2, 324 GL_BGRA, GL_FLOAT, BUFFER_OFFSET(0)); 325 326 // change the binding point of the buffer object to 327 // the vertex array binding point 328 BindBuffer(GL_ARRAY_BUFFER, vertexBuffer); 329 330 EnableClientState(VERTEX_ARRAY); 331 VertexPointer(4, FLOAT, 0, BUFFER_OFFSET(0)); 332 DrawArrays(TRIANGLE_STRIP, 0, numberVertices); 333 334 Example 2: Streaming textures 335 336 streaming textures using NV_pixel_data_range 337 338 void *pdrMemory, *texData; 339 340 pdrMemory = AllocateMemoryNV(texsize, 0.0, 1.0, 1.0); 341 342 PixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV, texsize, pdrMemory); 343 344 EnableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV); 345 346 // setup texture environment 347 ... 348 349 texData = getNextImage(); 350 351 while (texData) { 352 353 memcpy(pdrMemory, texData, texsize); 354 355 FlushPixelDataRangeNV(GL_WRITE_PIXEL_DATA_RANGE_NV); 356 357 TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 358 texWidth, texHeight, GL_BGRA, GL_UNSIGNED_BYTE, pdrMemory); 359 360 // draw textured geometry 361 Begin(GL_QUADS); 362 ... 363 End(); 364 365 texData = getNextImage(); 366 } 367 368 DisableClientState(GL_WRITE_PIXEL_DATA_RANGE_NV); 369 370 FreeMemoryNV(pdrMemory); 371 372 streaming textures using EXT_pixel_buffer_object: 373 374 void *pboMemory, *texData; 375 376 // create and bind texture image buffer object 377 GenBuffers(1, &texBuffer); 378 BindBuffer(PIXEL_UNPACK_BUFFER_EXT, texBuffer); 379 BufferData(PIXEL_UNPACK_BUFFER_EXT, texSize, NULL, STREAM_DRAW); 380 381 texData = getNextImage(); 382 383 while (texData) { 384 385 // map the texture image buffer 386 pboMemory = MapBuffer(PIXEL_UNPACK_BUFFER_EXT, WRITE_ONLY); 387 388 // modify (sub-)buffer data 389 memcpy(pboMemory, texData, texsize); 390 391 // unmap the texture image buffer 392 if (!UnmapBuffer(PIXEL_UNPACK_BUFFER_EXT)) { 393 // Handle error case 394 } 395 396 // update (sub-)teximage from texture image buffer 397 TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, 398 GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); 399 400 // draw textured geometry 401 Begin(GL_QUADS); 402 ... 403 End(); 404 405 texData = getNextImage(); 406 } 407 408 BindBuffer(PIXEL_UNPACK_BUFFER_EXT, 0); 409 410 Example 3: Asynchronous ReadPixels 411 412 traditional ReadPixels 413 414 unsigned int readBuffer[imagewidth*imageheight*4]; 415 416 // render to framebuffer 417 DrawBuffer(GL_BACK); 418 renderScene() 419 420 // read image from framebuffer 421 ReadBuffer(GL_BACK); 422 ReadPixels(); 423 424 // process image when ReadPixels returns after reading the whole buffer 425 processImage(readBuffer); 426 427 asynchronous ReadPixels 428 429 GenBuffers(2, imageBuffers); 430 431 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[0]); 432 BufferData(PIXEL_PACK_BUFFER_EXT, imageSize / 2, NULL, STATIC_READ); 433 434 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[1]); 435 BufferData(PIXEL_PACK_BUFFER_EXT, imageSize / 2, NULL, STATIC_READ); 436 437 // render to framebuffer 438 DrawBuffer(GL_BACK); 439 renderScene(); 440 441 // Bind two different buffer objects and start the ReadPixels 442 // asynchronously. Each call will return directly after starting the 443 // DMA transfer. 444 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[0]); 445 ReadPixels(0, 0, width, height/2, 446 GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0)); 447 448 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[1]); 449 ReadPixels(0, height/2, width, height/2, GL_BGRA, GL_UNSIGNED_BYTE, 450 BUFFER_OFFSET(0)); 451 452 // process partial images 453 pboMemory1 = MapBuffer(PIXEL_PACK_BUFFER_EXT, READ_ONLY); 454 processImage(pboMemory1); 455 pboMemory2 = MapBuffer(PIXEL_PACK_BUFFER_EXT, READ_ONLY); 456 processImage(pboMemory2); 457 458 // unmap the image buffers 459 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[0]); 460 if (!UnmapBuffer(PIXEL_PACK_BUFFER_EXT)) { 461 // Handle error case 462 } 463 BindBuffer(PIXEL_PACK_BUFFER_EXT, imageBuffers[1]); 464 if (!UnmapBuffer(PIXEL_PACK_BUFFER_EXT)) { 465 // Handle error case 466 } 467