• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    NV_pixel_buffer_object
4
5Name Strings
6
7    GL_NV_pixel_buffer_object
8
9Contributors
10
11    Contributors to ARB_pixel_buffer_object
12    Greg Roth, NVIDIA
13
14Contact
15
16    Mathias Heyer, NVIDIA Corporation (mheyer 'at' nvidia.com)
17
18Status
19
20    Complete.
21
22Version
23
24    Last Modified Date: April 27th, 2020
25    Revision: 3.0
26
27Number
28
29    OpenGL ES Extension #134
30
31Dependencies
32
33    Written based on the wording of the OpenGL ES 2.0 specification.
34
35    OES_mapbuffer affects the definition of this specification
36    EXT_map_buffer_range affects the definition of this specification
37
38Overview
39
40    This extension permits buffer objects to be used not only with vertex
41    array data, but also with pixel data.  The intent is to provide more
42    acceleration opportunities for OpenGL pixel commands.
43
44    While a single buffer object can be bound for both vertex arrays and
45    pixel commands, we use the designations vertex buffer object (VBO)
46    and pixel buffer object (PBO) to indicate their particular usage in
47    a given situation.
48
49    This extension does not add any new functionality to buffer objects
50    themselves.  It simply adds two new targets to which buffer objects
51    can be bound: GL_PIXEL_PACK_BUFFER_NV and GL_PIXEL_UNPACK_BUFFER_NV.
52    When a buffer object is bound to the GL_PIXEL_PACK_BUFFER_NV target,
53    commands such as glReadPixels pack (write) their data into a buffer
54    object. When a buffer object is bound to the GL_PIXEL_UNPACK_BUFFER_NV
55    target, commands such as glTexImage2D unpack (read) their
56    data from a buffer object.
57
58    There are a several approaches to improve graphics performance
59    with PBOs.  Some of the most interesting approaches are:
60
61    - Streaming texture updates:  If the application uses
62      glMapBufferOES/glMapBufferRangeEXT/glUnmapBufferOES to write
63      its data for glTexSubImage into a buffer object, at least one of
64      the data copies usually required to download a texture can be
65      eliminated, significantly increasing texture download performance.
66
67    - Asynchronous glReadPixels:  If an application needs to read back a
68      number of images and process them with the CPU, the existing GL
69      interface makes it nearly impossible to pipeline this operation.
70      The driver will typically send the hardware a readback command
71      when glReadPixels is called, and then wait for all of the data to
72      be available before returning control to the application.  Then,
73      the application can either process the data immediately or call
74      glReadPixels again; in neither case will the readback overlap with
75      the processing.  If the application issues several readbacks
76      into several buffer objects, however, and then maps each one to
77      process its data, then the readbacks can proceed in parallel with
78      the data processing.
79
80    - Render to vertex array:  The application can use a fragment
81      program to render some image into one of its buffers, then read
82      this image out into a buffer object via glReadPixels.  Then, it can
83      use this buffer object as a source of vertex data.
84
85
86New Procedures and Functions
87
88    None.
89
90
91New Tokens
92
93    Accepted by the <target> parameters of BindBuffer, BufferData,
94    BufferSubData, MapBufferOES, MapBufferRangeEXT, UnmapBufferOES,
95    FlushMappedBufferRangeEXT, GetBufferParameteriv, and
96    GetBufferPointervOES:
97
98        PIXEL_PACK_BUFFER_NV                        0x88EB
99        PIXEL_UNPACK_BUFFER_NV                      0x88EC
100
101    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
102    GetFloatv:
103
104        PIXEL_PACK_BUFFER_BINDING_NV                0x88ED
105        PIXEL_UNPACK_BUFFER_BINDING_NV              0x88EF
106
107
108Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL Operation)
109
110 -- Section 2.9 "Buffer Objects"
111
112    Replace the first two paragraphs with:
113
114    "The vertex data arrays described in section 2.8 are stored in
115    client memory.  It is sometimes desirable to store frequently accessed
116    client data, such as vertex array and pixel data, in high-performance
117    server memory.  GL buffer objects provide a mechanism for clients to
118    use to allocate, initialize, and access such memory."
119
120    The name space for buffer objects is the unsigned integer, with zero
121    reserved for the GL.  A buffer object is created by binding an unused
122    name to a buffer target.  The binding is effected by calling
123
124       void BindBuffer(enum target, uint buffer);
125
126    <target> must be one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
127    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV.  The ARRAY_BUFFER
128    target is discussed in section 2.9.1  The ELEMENT_ARRAY_BUFFER target
129    is discussed in section 2.9.2.  The PIXEL_UNPACK_BUFFER_NV and
130    PIXEL_PACK_BUFFER_NV targets are discussed later in sections 3.7.1 and
131    4.3.  If the buffer object named <buffer> has not been
132    previously bound or has been deleted since the last binding, the
133    GL creates a new state vector, initialized with a zero-sized memory
134    buffer and comprising the state values listed in table 2.5."
135
136    Replace the 5th paragraph with:
137
138    "Initially, each buffer object target is bound to zero.  There is
139    no buffer object corresponding to the name zero so client attempts
140    to modify or query buffer object state for a target bound to zero
141    generate an INVALID_OPERATION error."
142
143    Replace the phrase listing the valid targets for BufferData in the
144    9th paragraph with:
145
146    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
147    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV,"
148
149    In the 10th paragraph describing buffer object usage modes, replace
150    the phrase "specified once" with "specified once per repetition of
151    the usage pattern" for the STREAM_* and STATIC_* usage values.
152
153    Also in the 10th paragraph describing buffer object usage modes,
154    replace the phrases "of a GL drawing command." and "for GL drawing
155    commands." with "for GL drawing and image specification commands." for
156    the *_DRAW usage values.
157
158    Replace the phrase listing the valid targets for BufferSubData with:
159
160    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
161    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV."
162
163    Replace the phrase listing the valid targets for MapBufferOES with:
164
165    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
166    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV."
167
168    Replace the phrase listing the valid targets for UnmapBufferOES with:
169
170    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
171    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV."
172
173    Replace the phrase listing the valid targets for MapBufferRangeEXT
174    with:
175
176    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
177    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV."
178
179    Replace the phrase listing the valid targets for
180    FlushMappedBufferRangeEXT with:
181
182    "with <target> set to one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER,
183    PIXEL_UNPACK_BUFFER_NV, or PIXEL_PACK_BUFFER_NV."
184
185 -- Section 2.9.2 "Array Indices in Buffer Objects"
186
187    Delete the 3rd paragraph that explains how the ELEMENT_ARRAY_BUFFER
188    target is acceptable for the commands specified in section 2.9.
189    The updated section 2.9 language already says this.
190
191Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization)
192
193 -- Section 3.6 "Pixel Rectangles"
194
195    Replace the last two paragraphs with:
196
197    "This section describes only how these rectangles are defined in
198     buffer object and client memory, and the steps involved in
199     transferring pixel rectangles from buffer object or client memory
200     to the GL or vice-versa.
201     Parameters controlling the encoding of pixels in buffer object or
202     client memory (for reading and writing) are set with the command
203     PixelStorei."
204
205 -- Rename Section 3.6.1 "Pixel Storage Modes and Pixel Buffer Objects"
206
207    Add to the end of the section:
208
209    "In addition to storing pixel data in client memory, pixel data
210    may also be stored in buffer objects (described in section 2.9).
211    The current pixel unpack and pack buffer objects are designated
212    by the PIXEL_UNPACK_BUFFER_NV and PIXEL_PACK_BUFFER_NV targets
213    respectively.
214
215    Initially, zero is bound for the PIXEL_UNPACK_BUFFER_NV, indicating
216    that image specification commands such as TexImage*D source their
217    pixels from client memory pointer parameters.  However, if a non-zero
218    buffer object is bound as the current pixel unpack buffer, then
219    the pointer parameter is treated as an offset into the designated
220    buffer object."
221
222
223 -- Section 3.6.2 "Transfer of Pixel Rectangles", page 61.
224
225    Change the 1st sentence of the 1st paragraph to read:
226
227    "The process of transferring pixels encoded in buffer object
228     or client memory is diagrammed in figure 3.5."
229
230    Change the 4th sentence of the 2nd paragraph to read:
231
232    "<data> refers to the data to be transferred."
233
234    [data is no longer necessarily a pointer.]
235
236    Change the initial phrase in the 1st sentence of the 1st paragraph
237    in subsection "Unpacking" to read:
238
239    "Data are taken from the currently bound pixel unpack buffer or
240    client memory as a sequence of..."
241
242    Insert this paragraph after the 1st paragraph in subsection
243    "Unpacking":
244
245    "If a pixel unpack buffer is bound (as indicated by a non-zero
246    value of PIXEL_UNPACK_BUFFER_BINDING_NV), <data> is an offset
247    into the pixel unpack buffer and the pixels are unpacked from the
248    buffer relative to this offset; otherwise, <data> is a pointer to
249    a block client memory and the pixels are unpacked from the client
250    memory relative to the pointer.  If a pixel unpack buffer object
251    is bound and unpacking the pixel data according to the process
252    described below would access memory beyond the size of the pixel
253    unpack buffer's memory size, INVALID_OPERATION results.  If a pixel
254    unpack buffer object is bound and <data> is not evenly divisible
255    into the number of basic machine units needed to store in memory the
256    corresponding GL data type from table 3.4 for the <type> parameter,
257    INVALID_OPERATION results."
258
259 -- Section 3.7.1 "Texture Image Specification", page 66.
260
261    Replace the last phrase in the 2nd to last sentence in the 1st
262    paragraph with:
263
264    "and a reference to the image data in the currently bound pixel unpack
265    buffer or client memory, as described in section 3.6.2."
266
267    Replace the 1st sentence in the 9th paragraph with:
268
269    "The image itself (referred to by <data>) is a sequence of groups
270    of values."
271
272    Replace the last paragraph with:
273
274    "If the data argument of TexImage2D is a NULL pointer, and the
275     pixel unpack buffer object is zero, a two- or three-dimensional
276     texel array is created with the specified target, level, internalformat,
277     border, width, height, and depth, but with unspecified image contents.
278     In this case no pixel values are accessed in client memory, and no pixel
279     processing is performed. Errors are generated, however, exactly as though
280     the data pointer were valid. Otherwise if the pixel unpack buffer object
281     is non-zero, the data argument is treatedly normally to refer to the
282     beginning of the pixel unpack buffer object's data."
283
284 -- Section 3.7.3 "Compressed Texture Images", page 73.
285
286    Replace the 3rd sentence of the 2nd paragraph with:
287
288    "<data> refers to compressed image data stored in the compressed
289    image format corresponding to internalformat.  If a pixel
290    unpack buffer is bound (as indicated by a non-zero value of
291    PIXEL_UNPACK_BUFFER_BINDING_NV), <data> is an offset into the
292    pixel unpack buffer and the compressed data is read from the buffer
293    relative to this offset; otherwise, <data> is a pointer to a block
294    client memory and the compressed data is read from the client memory
295    relative to the pointer."
296
297    Replace the 2nd sentence in the 3rd paragraph with:
298
299    "Compressed texture images are treated as an array of <imageSize>
300    ubytes relative to <data>.  If a pixel unpack buffer object is bound
301    and data+imageSize is greater than the size of the pixel buffer,
302    INVALID_OPERATION results."
303
304Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment
305Operations and the Frame Buffer)
306
307 -- Section 4.3 "Reading Pixels", page 104.
308
309    Replace the first paragraph with:
310
311    "Pixels may be read from the framebuffer to pixel pack buffer or
312     client memory using the ReadPixels commands, as described below.
313     Pixels may also be copied from pixel unpack buffer, client memory or
314     the framebuffer to texture images in the GL using the TexImage2D and
315     CopyTexImage2D commands, as described in section 3.7.1.
316
317 -- Section 4.3.1 "Reading Pixels", page 104.
318
319    Replace 1st sentence of the 1st paragraph with:
320
321    "The method for reading pixels from the framebuffer and placing them in
322    pixel pack buffer or client memory is diagrammed in figure 4.2."
323
324    Add this paragraph after the 1st paragraph:
325
326    "Initially, zero is bound for the PIXEL_PACK_BUFFER_NV, indicating
327    that image read and query commands such as ReadPixels return
328    pixels results into client memory pointer parameters.  However, if
329    a non-zero buffer object is bound as the current pixel pack buffer,
330    then the pointer parameter is treated as an offset into the designated
331    buffer object."
332
333    Rename "Placement in Client Memory" to "Placement in Pixel Pack
334    Buffer or Client Memory".
335
336    Insert this paragraph at the start of the newly renamed
337    subsection "Placement in Pixel Pack Buffer or Client Memory":
338
339    "If a pixel pack buffer is bound (as indicated by a non-zero value
340    of PIXEL_PACK_BUFFER_BINDING_NV), <data> is an offset into the
341    pixel pack buffer and the pixels are packed into the
342    buffer relative to this offset; otherwise, <data> is a pointer to a
343    block client memory and the pixels are packed into the client memory
344    relative to the pointer.  If a pixel pack buffer object is bound and
345    packing the pixel data according to the pixel pack storage state
346    would access memory beyond the size of the pixel pack buffer's
347    memory size, INVALID_OPERATION results.  If a pixel pack buffer object
348    is bound and <data> is not evenly divisible into the number of basic
349    machine units needed to store in memory the corresponding GL data type
350    from table 3.5 for the <type> parameter, INVALID_OPERATION results."
351
352
353Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions)
354
355    None
356
357
358Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State
359Requests)
360
361--- Section 6.1.3 Enumerated Queries
362
363    Change the 1st sentence of the 3rd paragraph to read:
364    "The command
365        void GetBufferParameteriv( enum target, enum value, T data );
366    returns information about <target>, which may be one of ARRAY_BUFFER,
367    ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV, PIXEL_UNPACK_BUFFER_NV
368    indicating the currently bound vertex array, element array, pixel pack
369    and pixel unpack buffer object."
370
371 -- Section 6.1.13 "Buffer Object Queries".
372
373    (description of glGetBufferPointervOES)
374    Change the 2nd sentence of the 2nd paragraph to read:
375    "<target> is ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV,
376    or PIXEL_UNPACK_BUFFER_NV."
377
378
379Errors
380
381    INVALID_ENUM is generated if the <target> parameter of
382    BindBuffer, BufferData, BufferSubData, MapBufferOES, UnmapBufferOES,
383    GetBufferParameteriv or GetBufferPointervOES is not
384    one of ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER, PIXEL_PACK_BUFFER_NV,
385    or PIXEL_UNPACK_BUFFER_NV.
386
387    INVALID_OPERATION is generated if CompressedTexImage2D,
388    CompressedTexSubImage2D, TexImage2D or TexSubImage2D would unpack
389    (read) data from the currently bound PIXEL_UNPACK_BUFFER_NV buffer
390    object such that the memory reads required for the command would exceed
391    the memory (data store) size of the buffer object.
392
393    INVALID_OPERATION is generated if ReadPixels or ReadnPixelsEXT
394    would pack (write) data to the currently bound PIXEL_PACK_BUFFER_NV
395    buffer object such that the memory writes required for the command would
396    exceed the memory (data store) size of the buffer object.
397
398    INVALID_OPERATION is generated by ReadPixels or ReadnPixelsEXT
399    if the current PIXEL_PACK_BUFFER_BINDING_NV value is non-zero and the
400    table/image/values/span/img/data parameter is not evenly divisible
401    into the number of basic machine units needed to store in memory a
402    datum indicated by the type parameter.
403
404    INVALID_OPERATION is generated by TexImage2D or TexSubImage2D
405    if current PIXEL_UNPACK_BUFFER_BINDING_NV value is non-zero and the data
406    parameter is not evenly divisible into the number of basic machine
407    units needed to store in memory a datum indicated by the type
408    parameter.
409
410Dependencies on OES_mapbuffer
411
412    If OES_mapbuffer is not present, references to MapBufferOES and
413    UnmapBufferOES should be ignored and language referring to mapped
414    buffer objects should be removed.
415
416Dependencies on EXT_map_buffer_range
417
418    If EXT_map_buffer_range is not present, references to
419    MapBufferRangeEXT anf FlushMappedBufferRangeEXT should be ignored.
420
421New State
422
423(table 6.13, Pixels, p. 147)
424
425                                                         Initial
426    Get Value                        Type   Get Command  Value    Sec
427    -------------------------------  ----   -----------  -------  ------
428    PIXEL_PACK_BUFFER_BINDING_NV    Z+     GetIntegerv  0        4.3.1
429    PIXEL_UNPACK_BUFFER_BINDING_NV  Z+     GetIntegerv  0        3.6.1
430
431
432
433Usage Examples
434
435    Convenient macro definition for specifying buffer offsets:
436
437        #define BUFFER_OFFSET(i) ((char *)NULL + (i))
438
439    Example 1: Render to vertex array:
440
441        const int numberVertices = 100;
442
443        // Create a buffer object for a number of vertices consisting of
444        // 4 float values per vertex
445        glGenBuffers(1, vertexBuffer);
446        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, vertexBuffer);
447        glBufferData(GL_PIXEL_PACK_BUFFER_NV, numberVertices*4,
448                     NULL, GL_DYNAMIC_DRAW);
449
450        // Render vertex data into 100x1 strip of framebuffer using a
451        // shader program
452        glUseProgram(program);
453        renderVertexData();
454        glBindProgramARB(FRAGMENT_PROGRAM_ARB, 0);
455
456        // Read the vertex data back from framebuffer
457        glReadPixels(0, 0, numberVertices, 1, GL_BGRA, GL_UNSIGNED_BYTE,
458                     BUFFER_OFFSET(0));
459
460        // Change the binding point of the buffer object to
461        // the vertex array binding point
462        glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
463
464        glEnableVertexAttribArray(0);
465        glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, BUFFER_OFFSET(0));
466        glDrawArrays(TRIANGLE_STRIP, 0, numberVertices);
467
468
469    Example 2: Streaming textures
470
471    Streaming textures using pixel buffer objects:
472
473        const int texWidth = 256;
474        const int texHeight = 256;
475        const int texsize = texWidth * texHeight * 4;
476        void *pboMemory, *texData;
477
478        // Define texture level zero (without an image); notice the
479        // explicit bind to the zero pixel unpack buffer object so that
480        // pass NULL for the image data leaves the texture image
481        // unspecified.
482        glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, 0);
483        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0,
484                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
485
486        // Create and bind texture image buffer object
487        glGenBuffers(1, &texBuffer);
488        glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, texBuffer);
489
490        // Setup texture environment
491        ...
492
493        texData = getNextImage();
494
495        while (texData) {
496
497            // Reset the contents of the texSize-sized buffer object
498            glBufferData(GL_PIXEL_UNPACK_BUFFER_NV, texSize, NULL,
499                         GL_STREAM_DRAW);
500
501            // Map the texture image buffer (the contents of which
502            // are undefined due to the previous glBufferData)
503            pboMemory = glMapBufferOES(GL_PIXEL_UNPACK_BUFFER_NV,
504                                    GL_WRITE_ONLY);
505
506            // Modify (sub-)buffer data
507            memcpy(pboMemory, texData, texsize);
508
509            // Unmap the texture image buffer
510            glUnmapBufferOES(GL_PIXEL_UNPACK_BUFFER_NV);
511
512            // Update (sub-)teximage from texture image buffer
513            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight,
514                            GL_RGBA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
515
516            // Draw textured geometry
517            ...
518
519            texData = getNextImage();
520        }
521
522        glBindBuffer(GL_PIXEL_UNPACK_BUFFER_NV, 0);
523
524
525    Example 3: Asynchronous glReadPixels
526
527    Traditional glReadPixels:
528
529        const int imagewidth = 640;
530        const int imageheight = 480;
531        GLubyte readBuffer[imagewidth*imageheight*4];
532
533        // Render to framebuffer
534        renderScene()
535
536        // Read image from framebuffer
537        glReadPixels(0, 0, imagewidth, imageheight, GL_RGBA,
538                     GL_UNSIGNED_BYTE, readBuffer);
539
540        // Process image when glReadPixels returns after reading the
541        // whole buffer
542        processImage(readBuffer);
543
544
545    Asynchronous glReadPixels:
546
547        const int imagewidth = 640;
548        const int imageheight = 480;
549        const int imageSize = imagewidth*imageheight*4;
550
551        glGenBuffers(2, imageBuffers);
552
553        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]);
554        glBufferData(GL_PIXEL_PACK_BUFFER_NV, imageSize / 2, NULL,
555                     GL_STREAM_DRAW);
556
557        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]);
558        glBufferData(GL_PIXEL_PACK_BUFFER_NV, imageSize / 2, NULL,
559                     GL_STREAM_DRAW);
560
561        // Render to framebuffer
562        glDrawBuffer(GL_BACK);
563        renderScene();
564
565        // Bind two different buffer objects and start the glReadPixels
566        // asynchronously. Each call will return directly after
567        // starting the DMA transfer.
568        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]);
569        glReadPixels(0, 0, imagewidth, imageheight/2, GL_RGBA,
570                     GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
571
572        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]);
573        glReadPixels(0, imageheight/2, imagewidth, imageheight/2, GL_RGBA,
574                     GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
575
576        // Process partial images.  Mapping the buffer waits for
577        // outstanding DMA transfers into the buffer to finish.
578        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]);
579        pboMemory1 = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER_NV, 0,
580                                         imageSize/2, GL_MAP_READ_BIT_EXT);
581        processImage(pboMemory1);
582        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]);
583        pboMemory2 = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER_NV, 0,
584                                         imageSize/2, GL_MAP_READ_BIT_EXT);
585        processImage(pboMemory2);
586
587        // Unmap the image buffers
588        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[0]);
589        glUnmapBuffer(GL_PIXEL_PACK_BUFFER_NV);
590        glBindBuffer(GL_PIXEL_PACK_BUFFER_NV, imageBuffers[1]);
591        glUnmapBuffer(GL_PIXEL_PACK_BUFFER_NV);
592
593
594Issues
595
596
597    1)  Can a given buffer be used for both vertex and pixel data?
598
599        RESOLVED: YES.  All buffers can be used with all buffer bindings,
600        in whatever combinations the application finds useful.  Consider
601        yourself warned, however, by the following issue.
602
603    2)  May implementations make use of the target as a hint to select
604        an appropriate memory space for the buffer?
605
606        RESOLVED: YES, as long as such behavior is transparent to the
607        application. Some implementations may choose different memory
608        spaces for different targets.
609        In fact, one can imagine arbitrarily complicated heuristics for
610        selecting the memory space, based on factors such as the target,
611        the "usage" argument, and the application's observed behavior.
612
613        While it is entirely legal to create a buffer object by binding
614        it to GL_ARRAY_BUFFER and loading it with data, then using it
615        with the GL_PIXEL_UNPACK_BUFFER_NV or GL_PIXEL_PACK_BUFFER_NV
616        binding, such behavior is liable to confuse the driver and may
617        hurt performance.  If the driver implemented the hypothetical
618        heuristic described earlier, such a buffer might have already
619        been located in AGP memory, and so the driver would have to choose
620        between two bad options: relocate the buffer into video memory, or
621        accept lower performance caused by streaming pixel data from AGP.
622
623    3)  Should the INVALID_OPERATION error be generated if a pixel
624        command would access data outside the range of the bound PBO?
625
626        RESOLVED:  YES.  This requires considering the command parameters
627        (such as width/height/depth/format/type/pointer), the current
628        pixel store (pack/unpack) state, and the command operation itself
629        to determine the maximum addressed byte for the pixel command.
630
631        This behavior should increase the reliability of using PBO and
632        guard against programmer mistakes.
633
634        This is particularly important for glReadPixels where returning
635        data into a region outside the PBO could cause corruption of
636        application memory.
637
638        Such bounds checking is substantially more expensive for VBO
639        accesses because bounds checking on a per-vertex element basis
640        for each of multiple enabled vertex arrays prior to performing
641        the command compromises the performance justification of VBO.
642
643     4) If a pixel command with a bound PBO accesses data outside the
644        range of the PBO, thereby generating a GL_INVALID_OPERATION error,
645        can the pixel command end up being partially processed?
646
647        RESOLVED:  NO.  As for all GL errors excepting GL_OUT_OF_MEMORY
648        situations, "the command generating the error is ignored so that
649        it has no effect on GL state or framebuffer contents."
650
651        This means implementations must determine before the pixel command
652        is performed whether the resulting read or write operations on
653        the bound PBO will exceed the size of the PBO.
654
655        This means an implementation is NOT allowed to detect out of
656        bounds accesses in the middle of performing the command.
657
658     5) Should an INVALID_OPERATION error be generated if the offset
659        within a pixel buffer to a datum comprising of N basic machine
660        units is not a multiple of N?
661
662        RESOLVED:  YES.  This was stated for VBOs but no error was
663        defined if the rule was violated.  Perhaps this needs to be
664        better specified for VBO.
665
666        For PBO, it is reasonable and cheap to enforce the alignment rule.
667        For pixel commands it means making sure the offset is evenly
668        divisible by the component or group size in basic machine units.
669
670        This check is independent of the pixel store state because the
671        pixel store state is specified in terms of pixels (not basic
672        machine units) so pixel store addressing cannot create an
673        unaligned access as long as the base offset is aligned.
674
675        Certain commands (specifically,
676        glCompressedTexImage2D, glCompressedTexSubImage2D) are not
677        affected by this error because the data accessed is addressed
678        at the granularity of basic machine units.
679
680     6) Various commands do not make explicit reference to supporting
681        packing or unpacking from a pixel buffer object but rather specify
682        that parameters are handled in the same manner as glReadPixels,
683        or the glCompressedTexImage commands.  So do such
684        commands (example: glCompressedTexSubImage2D) use pixel buffers?
685
686        RESOLVED:  YES.  Commands that have their behavior defined based
687        on commands that read or write from pixel buffers will themselves
688        read or write from pixel buffers.  Relying on this reduces the
689        amount of specification language to be updated.
690
691     7) What is the complete list of commands that can unpack (read)
692        pixels from the current pixel unpack buffer object?
693
694            glCompressedTexImage2D
695            glCompressedTexSubImage2D
696            glTexImage2D
697            glTexSubImage2D
698
699     8) What is the complete list of commands that can pack (write)
700        pixels into the current pixel pack buffer object?
701
702            glReadPixels
703
704     9) Prior to this extension, passing zero for the data argument of
705        glTexImage2D defined a texture image level without supplying an image.
706        How does this behavior change with this extension?
707
708        RESOLVED:  The "unspecified image" behavior of the glTexImage
709        calls only applies when bound to a zero pixel unpack buffer
710        object.
711
712        When bound to a non-zero pixel unpack buffer object, the data
713        argument to these calls is treated as an offset rather than
714        a pointer so zero is a reasonable and even likely value that
715        corresponds to the very beginning of the buffer object's data.
716
717        So to create a texture image level with unspecified image data,
718        you MUST bind to the zero pixel unpack buffer object.
719
720        See the ammended language at the end of section 3.7.1.
721
722    10) How does this extension support video frame grabbers?
723
724        RESOLVED:  This extension extends buffer objects so they can
725        operate with pixel commands, rather than just vertex array
726        commands.
727
728        We anticipate that a future extension may provide a mechanism
729        for transferring video frames from video frame grabber hardware
730        or vertices from motion capture hardware (or any other source
731        of aquired real-time data) directly into a buffer object to
732        eliminate a copy.  Ideally, such transfers would be possible
733        without requiring mapping of the buffer object.  But this
734        extension does not provide such functionality.
735
736        We anticipate such functionality to involve binding a buffer
737        object to a new target type, configuring a source (or sink) for
738        data (video frames, motion capture vertex sets, etc.), and then
739        commands to initiate data transfers to the bound buffer object.
740
741    11) Is this the "right" way to expose render-to-vertex-array?
742
743        DISCUSSION:  You can use this extension to render an image
744        into a framebuffer, copy the pixels into a buffer object with
745        glReadPixels, and then configure vertex arrays to source the pixel
746        data as vertex attributes.  This necessarily involves a copy
747        from the framebuffer to the buffer object.  Future extensions
748        may provide mechanisms for copy-free render-to-vertex-array
749        capabilities but that is not a design goal of this extension.
750
751Revision History
752
753    3   04/27/2020 fix example code: GL_STREAM_READ is not available in ES2.0
754                   glMapBufferOES does not allow reading from the mapped pointer.
755    2   10/23/2012 more cleanup, interaction with EXT_map_buffer_range
756    1   04/19/2012 initial revision
757        - took ARB_pixel_buffer_object, stripped everything not applicable to
758          ES, changed references to tables and sections; changed all wording
759          to fit ES' language.
760
761