• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    APPLE_object_purgeable
4
5Name Strings
6
7    GL_APPLE_object_purgeable
8
9Contributors
10
11    Andrew Barnes
12    Bob Beretta
13    Kenneth Dyke
14    Alex Eddy
15    John Harper
16    Charlie Lao
17    Jeremy Sandmel
18
19Contact
20
21    Charlie Lao, Apple Computer Inc. (clao 'at' apple.com)
22
23Status
24
25    TBD
26
27Version
28
29    Last Modified Date: September 29, 2006
30
31Number
32
33    371
34
35Dependencies
36
37    OpenGL 1.5 is required.
38
39    The extension is written against the OpenGL 1.5 Specification.
40
41Overview
42
43    This extension provides the ability to mark the storage of OpenGL
44    objects as "purgeable".
45
46    Many of today's modern virtual memory systems include the concept of
47    purgeability in order to avoid unnecessary paging when the object
48    contents are no longer needed.  In OpenGL, objects such as textures,
49    vertex buffers, pixel buffers, and renderbuffers all have
50    significant storage requirements.  By default, the OpenGL is
51    required to preserve the contents of these objects regardless of
52    system resource stress, such as vram shortage or physical memory
53    shortage.  Often this is accomplished by temporarily paging the
54    contents of objects that are not currently needed to some kind of
55    secondary storage area.  This paging operation can be an unnecessary
56    computational expense in the cases where the data is not going to be
57    used again or where the content can be reproduced by the application
58    with less expense than the paging operation would require.
59
60    This extension defines a mechanism for the application to mark the
61    storage of OpenGL objects as "purgeable" in order to influence these
62    paging operations.  The application can further control the
63    semantics of making object storage "purgeable" with two options
64    ("volatile" and "released") and "unpurgeable" with two options
65    ("undefined" and "retained")
66
67    Applications that use this extension will typically follow one of
68    two operational models.  The typical model for most applications is
69    to mark an object storage as "purgeable" with the "volatile" option,
70    and then later mark the storage as "unpurgeable" with the "retained"
71    option. When this happens, the application may or may not need to
72    respecify the object contents, depending on the whether the object
73    storage was actually released.  The application can find out whether
74    the storage was released by examining the return value of the
75    function which marks the storage as "unpurgeable".  This model is
76    useful when the application does not know at the time it marks the
77    object storage as "purgeable" whether it will later need those
78    contents to be valid.
79
80    Another operational model is for an application to mark the storage
81    for an object as "purgeable" with the "released" option, and then
82    later mark the object "unpurgeable" with the "undefined" option.  In
83    this latter model, the application intends to unconditionally reload
84    the object contents later on, and so it tells the GL that it is okay
85    if the contents are "undefined" when the storage is re-allocated.
86
87    Note that in both models, it is possible for the contents to become
88    undefined since they could have actually been purged from the system
89    in either case.  The various options are still useful, however,
90    since they give more information to the GL about what the
91    application expects to happen and the GL can use this information to
92    make better predictions about which paging choices will be more
93    efficient.
94
95IP Status
96
97    No known IP claims.
98
99Issues
100
101    1. Why use two functions rather than just one?
102
103        The reason we chose two functions is that switching between the
104        two possible object states - purgeable and unpurgeable - might
105        be expensive.  In addition, the return values of the operation
106        may be different depending on what state the object storage is
107        in and whether it has been purged or not.  Therefore, we want to
108        enforce that the state is changed in matching pairs of function
109        calls, similar to Begin/End.  In order to enforce this behavior,
110        we require two functions.
111
112        Applications are required to call ObjectPurgeable and
113        ObjectUnpurgeable in matched pairs, otherwise INVALID_OPERATION
114        is generated.
115
116    2. What does calling ObjectUnpurgeable with <option> set to
117       UNDEFINED_APPLE really mean?
118
119        An application calls ObjectUnpurgeable in order to change the
120        state of the object storage to unpurgeable.  This is the
121        "default" state for object storage as defined traditionally in
122        GL.
123
124        Further, by using the <option> of UNDEFINED_APPLE, the
125        application is also indicating that it does not care about the
126        previous contents of the storage, if they still exist.  This
127        gives the GL the freedom to allocate new storage or simply reuse
128        the old storage without spending time to figure out whether the
129        storage was actually freed and without having to tell the
130        application which choice was made. In addition, this allows the
131        function to return without blocking.
132
133        In contrast, calling ObjectUnpurgeable with <option> set to
134        RETAINED_APPLE requests the GL actually determine whether or not
135        it is possible to retain the original contents of the object,
136        and to restore the object storage to the previous contents, if
137        they still exist.  This operation generally requires a flush of
138        the current command stream and often involveds additional work
139        to determine the state of object.
140
141    3. What's the difference between calling ObjectPurgeable and calling
142       DeleteTextures?
143
144        Calling ObjectPurgeable allows the GL to release all storage
145        that the GL has allocated for the object's contents, but will
146        still retain the object name and other non-content related state
147        of the object.  If the application intends to re-use the object
148        again later, it will indicate so calling ObjectUnpurgeable.
149
150        In contrast, DeleteTextures deletes the object storage, the
151        object name, and the rest of the object state.  The object can
152        never again be used.
153
154        Note that this means to set the object's name as unused and to
155        delete non-content related state of the object, the application
156        is still responsible for calling DeleteTextures.
157
158        There are some additional subtle differences though.
159
160        In general, calling ObjectPurgeable with the <option>
161        VOLATILE_APPLE requires less work of the GL than calling
162        ObjectPurgeable with the <option> set to RELEASED_APPLE.
163        Further, calling ObjectPurgeable with either option generally
164        requires less work of the GL than DeleteTextures.
165
166        Applications are encouraged, therefore, to use ObjectPurgeable
167        with the <option> set to VOLATILE_APPLE where possible and fall
168        back to ObjectPurgeable with the <option> set to RELEASED_APPLE
169        only if they prefer to have the GL do some amount of work to try
170        to release the storage.  Only if the application really requires
171        the deletion of the object itself, should the application use
172        DeleteTextures.
173
174        Finally note, though the discussion above refers to
175        DeleteTextures, the same semantics apply to all object types
176        with Delete* operations, such as DeleteBuffers,
177        DeleteRenderbuffers, etc. that support this extension.
178
179    4. What should happen when ObjectPurgeable or ObjectUnpurgeable is
180       called between Begin/End?
181
182        This is illegal and returns INVALID_OPERATION error.
183
184    5. What should happen if ObjectPurgeable or ObjectUnpurgeable is
185       called on a currently bound texture, whether it is bound to the
186       current context or another context?
187
188        If the current context marks the storage of a currently bound
189        object as "purgeable", then attempts to read from or write to
190        the contents of that storage will result in undefined behavior.
191
192        Considering the multiple context case, we use the precedent of
193        all other state changes made by one context to an object bound
194        by another context.  Namely, changes made to an object by
195        context A or only guaranteed to be "visible" to context B the
196        next time context B binds that object.  In the interim period
197        the results of the state change are undefined.
198
199        For this extension, this means if context A marks an object's
200        storage as purgeable and that object is also bound by context B,
201        then it is undefined as to whether the object's storage will
202        have defined contents when used by context B. Note that in the
203        case of this particular extension, the whole point is to allow
204        the contents of the storage to become undefined so this is not a
205        particularly surprising outcome.
206
207        Applications are therefore advised to assume that they can not
208        rely on validity of the contents of any object whose storage has
209        been marked purgeable by any other context.  Further, until some
210        context has marked the object storage as "unpurgeable" again and
211        the current context has re-bound the object, the current context
212        should not assume the contents are valid either.  And even then
213        the contents should be assumed to be valid if and only if the
214        contents have been respecified or ObjectUnpurgeable returned the
215        value RETAINED_APPLE.
216
217    6. What should happen if the TestObject routine from the APPLE_fence
218       extension is called on an object whose storage has been marked
219       purgeable?
220
221        In short, it should operate "normally".
222
223        To be specific, if TestObject is called after calling
224        ObjectPurgeable with <option> set to VOLATILE_APPLE, the GL will
225        still determine if there are any pending operations using the
226        object, and TestObject will return TRUE or FALSE depending on
227        what it finds.
228
229        If TestObject is called after calling ObjectPurgeable with
230        <option> set to RELEASED_APPLE, the TestObject will generally
231        immediately return TRUE even though the object may still be in
232        use.  This is acceptable since from user's point of view, the
233        object's storage has been freed from further use by the GL.
234
235    7. How does APPLE_object_purgeable interact with the
236       APPLE_texture_range extension?
237
238        First note that depending on the value of the storage hint
239        provided in the APPLE_texture_range extension, the GL may have
240        made multiple copies of the texture data.
241
242        In general, calling ObjectPurgeable with <option> set to
243        VOLATILE_APPLE option indicates that the GL should mark the
244        multiple copies of the storage as candidates for eviction but
245        should only release them as needed.  In contrast, using the
246        <option> RELEASED_APPLE indicates that GL should try to go ahead
247        and release the storage for as many of these copies as is
248        efficient.
249
250    8. How does APPLE_object_purgeable interact with the
251       APPLE_client_storage extension?
252
253        For reference, APPLE_client_storage allows the application to
254        indicate that it will be responsible for allocating and
255        retaining the storage for a texture object.
256
257        In the APPLE_object_purgeable extension it is up to the
258        implementation to determine what happens when an object's
259        storage is marked purgeable and its up to the application to
260        query to determine whether the storage has been released.  Given
261        that, the APPLE_client_storage has no real practical
262        interactions with APPLE_object_purgeable.
263
264        However, if APPLE_client_storage is supported on a platform that
265        gives the application control over the volatility of of client
266        memory, for instance via some sort of virtual memory system
267        call, then it's possible the application use the
268        platform-specific virtual memory API to mark as volatile the the
269        memory backing a texture using APPLE_client_storage for its
270        storage.  The application on such a platform would be
271        responsible for using additional virtual memory system calls to
272        determine what happened to memory that was marked purgeable when
273        it goes to access that memory later on. In this scenario, the
274        effect would be very similar to the results of using the
275        APPLE_object_purgeable to mark a texture object's storage as
276        purgeable, but there is no direct interaction between the two
277        API's.
278
279    9. How does APPLE_object_purgeable interact with the
280       aglSurfaceTexture API?
281
282        For reference, the aglSurfaceTexture allows the application to
283        specify an AGL drawable as the storage for a GL texture object.
284        Such a texture object is informally called a "surface texture".
285
286        Similar to the APPLE_client_storage case, it is up to the API
287        that allocated the storage object to handle the purgeability of
288        that object.  Given that, the APPLE_client_storage has no real
289        practical interactions with AGL surface textures.
290
291
292    10. How does APPLE_object_purgeable interact with the
293        ARB_vertex_buffer_object and ARB_pixel_buffer_object extensions?
294
295        The interactions should be analogous to those that occur with
296        texture objects.
297
298        To mark the storage for a buffer object as purgeable or
299        unpurgeable, the application can specify BUFFER_OBJECT_APPLE as
300        the <objectType> parameter in ObjectPurgeable or
301        ObjectUnpurgeable, respectively.  The same rules about undefined
302        results from reading from or writing to the buffer object
303        storage while PURGEABLE_APPLE is TRUE apply as well.
304
305    13. After an object's storage has been marked as purgeable, what
306        should happen if CopyTexImage{1|2}D, CopyTexSubImage{1|2}D,
307        TexSubImage{1|2|3}D, or TexImage{1|2|3}D is called on the
308        texture? What if user try to texture from it or render to it?
309
310        After an object's storage has been marked purgeable, any usage
311        of the object is undefined until it is marked unpurgeable.
312
313
314New Procedures and Functions
315
316    enum ObjectPurgeableAPPLE(enum objectType, uint name, enum option)
317    enum ObjectUnpurgeableAPPLE(enum objectType, uint name, enum option)
318    void GetObjectParameterivAPPLE(enum objectType, uint name, enum
319                                   pname, int* params)
320
321New Types
322
323    None
324
325New Tokens
326
327    Accepted by the <option> parameter of ObjectPurgeable, and returned
328    by ObjectPurgeable:
329
330    RELEASED_APPLE        0x8A19
331    VOLATILE_APPLE        0x8A1A
332
333    Accepted by the <option> parameters of ObjectUnpurgeable, and
334    returned by ObjectUnpurgeable:
335
336    RETAINED_APPLE        0x8A1B
337    UNDEFINED_APPLE       0x8A1C
338
339    Accepted by the <pname> parameters of GetObjectParameteriv:
340
341    PURGEABLE_APPLE        0x8A1D
342
343    Accepted by the <objectType> parameters of ObjectPurgeableAPPLE,
344    ObjectUnpurgeableAPPLE and GetObjectParameteriv:
345
346    BUFFER_OBJECT_APPLE        0x85B3
347
348    (Note: BUFFER_OBJECT_APPLE is also defined in APPLE_fence extension
349    with the same value.)
350
351Additions to Chapter 2 of the OpenGL 1.5 Specification
352(OpenGL Operation)
353
354    None
355
356Additions to Chapter 3 of the OpenGL 1.5 Specification (Rasterization)
357
358    Additions to Chapter 3 of OpenGL 1.5 Specification (Rasterization)
359
360    (add a new section 3.8.16)
361
362    3.8.16 Purgeability
363
364    The internal data storage of a texture object, renderbuffer object,
365    or buffer object has a boolean state, PURGEABLE_APPLE that
366    influences how the object's storage is managed by the GL.  The
367    initial value of PURGEABLE_APPLE is FALSE.  The application can
368    change the value of PURGEABLE_APPLE by using the routines below.
369
370    The routine
371
372      enum ObjectPurgeableAPPLE(enum objectType, uint name, enum option)
373
374    sets PURGEABLE_APPLE to TRUE for the object of type <objectType>
375    with the id <name>. <objectType> must be one of TEXTURE,
376    BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT. If ObjectPurgeableAPPLE is
377    called and PURGEABLE_APPLE is already TRUE, the error
378    INVALID_OPERATION is generated.
379
380    While PURGEABLE_APPLE is TRUE, the GL may release the storage for
381    this object and the results of issuing any commands that read from
382    or write to the storage of that object are undefined.
383
384    <option> must be either VOLATILE_APPLE or RELEASED_APPLE.  Calling
385    ObjectPurgeableAPPLE with either option sets PURGEABLE_APPLE to
386    TRUE, but the value of <option> is used by the GL as a hint to
387    indicate the application's intended future use of the named object's
388    storage.
389
390    By calling ObjectPurgeableAPPLE with an <option> of VOLATILE_APPLE,
391    the application is indicating that it does not know if it will want
392    to re-use the current contents of the object storage again later.
393    Further, the application is stating that it would like the GL to do
394    only the minimal amount of work required to set PURGEABLE_APPLE to
395    TRUE. If ObjectPurgeableAPPLE is called with an <option> of
396    VOLATILE_APPLE, then ObjectPurgeableAPPLE will also return the value
397    VOLATILE_APPLE.
398
399    In contrast, by calling ObjectPurgeableAPPLE with an <option> of
400    RELEASED_APPLE, the application is indicating that it does not
401    intend to re-use the contents of the storage again.  Further, the
402    application is stating that it is acceptable for the GL to do a more
403    work to encourage the GL to actually release the storage for the
404    object. The actual mechanism for releasing the storage is
405    implementation-dependent, but it may require some level of
406    synchronization and may flush the current context.   If
407    ObjectPurgeableAPPLE is called with an <option> of RELEASED_APPLE,
408    then ObjectPurgeableAPPLE may return either the value RELEASED_APPLE
409    or the value VOLATILE_APPLE.
410
411    If ObjectPurgeableAPPLE returns the value VOLATILE_APPLE, this means
412    that the storage for the object may not have been released when
413    ObjectPurgeableAPPLE returns.  In contrast, if ObjectPurgeableAPPLE
414    returns the value RELEASED_APPLE, this means that the storage for
415    the object has been released when ObjectPurgeableAPPLE returns.
416
417    The routine
418
419      enum ObjectUnpurgeableAPPLE(enum object, uint name, enum option)
420
421    sets the value of PURGEABLE_APPLE to FALSE for the object of type
422    <objectType> with the id <name>.  If ObjectUnpurgeableAPPLE is
423    called and PURGEABLE_APPLE is already FALSE, the error
424    INVALID_OPERATION is returned.
425
426    While PURGEABLE_APPLE is FALSE, the storage for an object will not
427    be released by the GL. This is the default state for object storage.
428
429    <option> must be either RETAINED_APPLE or UNDEFINED_APPLE.  Calling
430    ObjectUnpurgeableAPPLE with either option sets PURGEABLE_APPLE to
431    FALSE, but the value of <option> is used by the GL as a hint to
432    indicate the application's intended future use of the named object's
433    storage.
434
435    By calling ObjectUnpurgeableAPPLE with an <option> of
436    RETAINED_APPLE, the application is indicating that it would like to
437    re-use the contents of the storage, if the storage has not yet been
438    released.  Further, the application is stating that it is acceptable
439    for the GL to do more work to try to restore the storage the same
440    state it was in before PURGEABLE_APPLE was set to TRUE. The actual
441    mechanism for attempting to restore the storage of the object is
442    implementation-dependent, but it may require some level of
443    synchronization and may flush the current context.   If
444    ObjectUnpurgeableAPPLE is called with an <option> of RETAINED_APPLE,
445    then ObjectPurgeableAPPLE may return either the value RETAINED_APPLE
446    or the value UNDEFINED_APPLE.
447
448    In contrast, by calling ObjectUnpurgeableAPPLE with an <option> of
449    UNDEFINED_APPLE, the application is indicating that it intends to
450    recreate the contents of the storage from scratch.  Further, the
451    application is is stating that it would like the GL to do only the
452    minimal amount of work set PURGEABLE_APPLE to FALSE.   If
453    ObjectUnpurgeableAPPLE is called with the <option> set to
454    UNDEFINED_APPLE, then ObjectUnpurgeableAPPLE will return the value
455    UNDEFINED_APPLE.
456
457    If ObjectUnpurgeableAPPLE returns the value UNDEFINED_APPLE, the
458    storage is in the same state as a newly created object with
459    undefined contents. In contrast, if ObjectUnpurgeableAPPLE returns
460    the value RETAINED_APPLE, this means that the storage has the same
461    the same contents it did when PURGEABLE_APPLE was most recently set
462    to FALSE.
463
464
465Additions to Chapter 4 of the OpenGL 1.5 Specification (Per-Fragment
466Operations and the Frame Buffer)
467
468    None
469
470Additions to Chapter 5 of the OpenGL 1.5 Specification
471(Special Functions)
472
473    None
474
475Additions to Chapter 6 of the OpenGL 1.5 Specification (State and State
476Requests)
477
478    (In section 6.1.3, Enumerated Queries, in the list of state query
479    functions, add the following)
480
481        "void GetObjectParameterivAPPLE(enum  objectType,
482                                        int   name,
483                                        enum  pname,
484                                        void* params);"
485
486    (and add the following description to the end of this section)
487
488    "GetObjectParameterivAPPLE places in <params> information about the
489     object of type <objectType> with the id <name>. <objectType> must
490     be one of TEXTURE, BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT.
491     <name> must be a non-zero name of an object of type <type>.  If
492     <pname> is PURGEABLE_APPLE, then when GetObjectParameterivAPPLE
493     returns, <params> will contain the current value of PURGEABLE_APPLE
494     for the named object's storage.  Note that this query does not
495     return whether or not the object storage has been purged but simply
496     whether the state PURGEABLE_APPLE is set to TRUE or FALSE."
497
498Additions to Appendix A of the OpenGL 1.5 Specification (Invariance)
499
500    None
501
502Additions to the AGL/EGL/GLX/WGL Specifications
503
504    None
505
506Errors
507
508    INVALID_ENUM is generated if the <objectType> parameter of
509    ObjectPurgeableAPPLE or ObjectUnpurgeableAPPLE is not one of
510    TEXTURE, BUFFER_OBJECT_APPLE, RENDERBUFFER_EXT.
511
512    INVALID_ENUM is generated if the <option> parameter of
513    ObjectPurgeableAPPLE is not VOLATILE_APPLE or RELEASED_APPLE.
514
515    INVALID_ENUM is generated if the <option> parameter of
516    ObjectUnpurgeableAPPLE is not RETAINED_APPLE or UNDEFINED_APPLE.
517
518    INVALID_VALUE is generated if the <name> parameter of
519    ObjectUnpurgeableAPPLE or ObjectUnpurgeableAPPLE is zero.
520
521    INVALID_OPERATION is generated if either ObjectUnpurgeableAPPLE or
522    ObjectUnpurgeableAPPLE is called between the execution of Begin and
523    the corresponding execution of End.
524
525    INVALID_OPERATION is generated if ObjectPurgeableAPPLE is called on
526    an object with a current value of PURGEABLE set to TRUE
527
528    INVALID_OPERATION is generated if ObjectUnpurgeableAPPLE is called
529    on an object with a current value of PURGEABLE set to FALSE
530
531    INVALID_ENUM is generated if the <objectType> parameter of
532    GetObjectParameterivAPPLE is not one of TEXTURE,
533    BUFFER_OBJECT_APPLE, or RENDERBUFFER_EXT.
534
535    INVALID_VALUE is generated if the <name> parameter of
536    GetObjectParameterivAPPLE is not the name of an existing
537    object of type <objectType>.
538
539    INVALID_VALUE is generated if the <name> parameter of
540    GetObjectParameterivAPPLE is zero.
541
542    INVALID_ENUM is generated if the <pname> parameter of
543    GetObjectParameterivAPPLE is PURGEABLE_APPLE.
544
545
546New State
547
548    Each object type that supports this extension has the following new
549state:
550
551    Type  Get Command        Inital Value  Description   Section       Attribute
552    ----  -----------------  ------------  ------------  -------       ---------
553    Z2    GetObjectParameter  FALSE        GL_PURGEABLE_APPLE  3.8.16       -
554
555New Implementation Dependent State
556
557    None
558
559Sample Code
560
561    A "one shot" texture is a texture specified, used once, and then
562    respecified again before it's next use.  The sample code below shows
563    how to use APPLE_object_purgeable to handle "one shot" textures:
564
565        /* First, find out if the texture is purgeable already */
566        boolean purgeable = FALSE;
567        GetObjectParameter(TEXTURE, name, &purgeable);
568        if(purgeable)
569            ObjectUnpurgeable(TEXTURE, name, UNDEFINED_APPLE);
570
571        /* Now that the texture is unpurgeable, respecify its contents
572        */
573        BindTexture(TEXTURE_2D, name);
574        Enable(TEXTURE_2D);
575        TexImage2D(TEXTURE_2D, 0, RGBA, width, height, 0, RGBA,
576                   UNSIGNED_BYTE, pixels);
577
578        /* Draw using the texture */
579        MyDrawRoutine goes here(...);
580
581        /* Now mark the texture as purgeable */
582        ObjectPurgeable(TEXTURE, name, RELEASED_APPLE);
583
584    Texture speculative caching:  A FBO is created and texture_name is
585    attached to it. The application then renders to texture and is
586    expecting to use this texture later on.  In the mean time it does
587    not want the GL to page it off because it is easy to recreate if
588    needed.
589
590        /* during system idle time, bind the fbo and render into it */
591        BindFramebufferEXT(FRAMEBUFFER_EXT, fbo_name);
592        MyDrawRoutineToSpecifyTextureContents(...);
593
594        /* We've rendered into the texture but we don't necessarily  */
595        /* need for it to remain valid if the GL wants to release it */
596        /* so we mark it as purgeable                                */
597        ObjectPurgeable(TEXTURE, texture_name, VOLATILE_APPLE);
598
599        /* now do some other unrelated rendering */
600        MyOtherDrawRoutineGoesHere(...);
601
602        /* Some time passes and then the application wants to        */
603        /* use the texture, so it markes the texture storage as      */
604        /* unpurgeable and indicates it would like the GL to try to  */
605        /* retain the storage if it still exists                     */
606
607        obj_state = ObjectUnpurgeable(TEXTURE,
608                                      texture_name, RETAINED_APPLE);
609        if(obj_state == RETAINED_APPLE)
610        {
611            /* object storage was retained so we can go ahead and use it
612            */
613            BindTexture(TEXTURE_2D, texture_name);
614            MyDrawRoutineThatUsesTheOriginalTexture(...);
615        }
616        else /* object storage was lost */
617        {
618            /* We must recreate the original texture contents */
619            BindFramebufferEXT(FRAMEBUFFER_EXT, fbo_name);
620            MyDrawRoutineToRespecifyTextureContents(...);
621
622            /* object storage has been re-specified so we can go */
623            /* ahead and use it now                              */
624            BindFramebufferEXT(FRAMEBUFFER_EXT, 0);
625            BindTexture(TEXTURE_2D, texture_name);
626            MyDrawRoutineThatUsesTheOriginalTexture(...);
627        }
628
629Revision History
630
631    Revision 2, 2006/10/20
632      - updated issue language to remove some stale resolutions
633      - revised and clarified language in terms of application intent
634        for the various <option> flags instead of implementation details
635      - replaced IsPurgeable with GetObjectParameter
636      - renamed extension "APPLE_object_purgeable" instead of
637        "APPLE_object_purgeability" to correlate with new state variable
638        GL_PURGEABLE_APPLE.
639
640    Revision 1, 2006/09/29
641      - Initial checkin.
642
643
644
645