2008-07-16 05:09:04 +02:00
/*
2011-07-09 02:17:37 +02:00
BufferProvider - Abstraction for Buffer management during playback / render
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
Copyright ( C )
2008 , Hermann Vosseler < Ichthyostega @ web . de >
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
* * Lumiera * * is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation ; either version 2 of the License , or ( at your
option ) any later version . See the file COPYING for further details .
2010-12-17 23:28:49 +01:00
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-07-16 05:09:04 +02:00
2016-11-03 18:22:31 +01:00
/** @file buffer-provider.cpp
BufferProvider: reconsider and rearrange the public API
In the end I refrained from applying most of the changes I had intended.
I am aware that `BufferProvider` is still quite a massive structure,
yet with the implementation refactorings done thus far, it seems
to be reasonably clear and self-contained now.
It would be possible to totally overthrow the grown structure and
expose only the two handles (BuffDescr and BuffHandle), together with
a factory function, but I cannot see how this would help to make the
code clearer and more approachable. Maybe it would make the usage
more obvious from the client's perspective — yet, to be honest,
there are not ''that much clients'' to justify such a move.
Furthermore, the implementation is far from finished: for both of
the back-end lines, a fully production-strength implementation
must be created, that is able to operate in a highly concurrent
environment; very likely some lock-free messaging and hand-over
between threads will become necessary, adding to the complexity.
Thus it seems better to note the ''design critique'', but to
postpone any further refactorings to a point where we can watch
a fully developed Render Engine under production load.
2026-02-16 20:50:04 +01:00
* * Implementation details related to buffer allocation and lifecycle management in the render engine .
* * This translation unit comprises the " back side " of the public front - end , where calls from the
* * client are received and relayed to the appropriate part of the implementation back - end .
* * Furthermore , some of the API functions on the [ Buffer Descriptor ] ( \ ref BuffDescr ) and the
* * [ Buffer Handle ] ( \ ref BuffHandle ) are also directly implemented here , by forwarding them
* * through the related implementation APIs . The actual backend implementation however is
* * split out and isolated by the internal interfaces BufferProvider : : BufferStage ( for the
* * state and lifecycle management ) and BufferProvider : : BufferStore ( for memory handling ) .
* *
* * The actual backend implementations to use are configured in subclasses .
2016-11-03 18:20:10 +01:00
*/
2011-11-15 04:47:31 +01:00
# include "lib/error.hpp"
2018-11-15 23:42:43 +01:00
# include "steam/engine/buffer-provider.hpp"
2026-02-10 21:11:02 +01:00
# include "steam/engine/buffer-metadata.hpp" /////////////////////////OOO must be removed from here
2011-11-13 04:20:14 +01:00
# include "lib/util.hpp"
2011-09-22 18:57:06 +02:00
2026-02-16 22:38:23 +01:00
# include <utility>
using std : : move ;
2024-11-14 22:10:43 +01:00
using util : : isSameAdr ;
2008-07-16 05:09:04 +02:00
2018-11-15 23:55:13 +01:00
namespace steam {
2008-07-16 05:09:04 +02:00
namespace engine {
2011-09-04 01:54:36 +02:00
2024-07-27 17:17:02 +02:00
// storage for the default-marker constants
const TypeHandler TypeHandler : : RAW { } ;
BufferProvider: reconsider and rearrange the public API
In the end I refrained from applying most of the changes I had intended.
I am aware that `BufferProvider` is still quite a massive structure,
yet with the implementation refactorings done thus far, it seems
to be reasonably clear and self-contained now.
It would be possible to totally overthrow the grown structure and
expose only the two handles (BuffDescr and BuffHandle), together with
a factory function, but I cannot see how this would help to make the
code clearer and more approachable. Maybe it would make the usage
more obvious from the client's perspective — yet, to be honest,
there are not ''that much clients'' to justify such a move.
Furthermore, the implementation is far from finished: for both of
the back-end lines, a fully production-strength implementation
must be created, that is able to operate in a highly concurrent
environment; very likely some lock-free messaging and hand-over
between threads will become necessary, adding to the complexity.
Thus it seems better to note the ''design critique'', but to
postpone any further refactorings to a point where we can watch
a fully developed Render Engine under production load.
2026-02-16 20:50:04 +01:00
const LocalTag LocalTag : : UNKNOWN { } ;
2026-02-15 23:39:13 +01:00
const metadata : : Key metadata : : Key : : INVALID { HashVal ( 0 ) , size_t ( 0 ) } ; //////OOO consider to relocate those marker constants to somewhere more obvious
2011-09-04 01:54:36 +02:00
2011-11-14 01:43:29 +01:00
LUMIERA_ERROR_DEFINE ( BUFFER_MANAGEMENT , " Problem providing working buffers " ) ;
2011-09-23 15:31:20 +02:00
2011-07-09 02:17:37 +02:00
BufferProvider : : ~ BufferProvider ( ) { }
2011-09-04 01:54:36 +02:00
/** @internal verify the given descriptor.
* @ return true if it corresponds to a buffer
* currently locked and usable by client code
*/
bool
2026-02-16 00:42:23 +01:00
BufferProvider : : isValid ( HashVal id ) const
2011-09-04 01:54:36 +02:00
{
2026-02-15 23:39:13 +01:00
return bool ( bufferStage_ - > lookup ( id ) ) ;
2011-09-04 01:54:36 +02:00
}
2026-02-16 00:42:23 +01:00
bool
BufferProvider : : isAccessible ( HashVal id ) const
{
2026-02-16 22:38:23 +01:00
return bufferStage_ - > isAccessible ( id ) ;
2026-02-16 00:42:23 +01:00
}
2011-09-04 01:54:36 +02:00
2026-02-15 23:39:13 +01:00
size_t
BufferProvider : : getBufferSize ( HashVal id ) const
{
auto & key = bufferStage_ - > lookup ( id ) ;
return key . storageSize ( ) ;
}
2011-09-04 01:54:36 +02:00
2024-07-15 18:52:59 +02:00
BuffDescr
2011-09-21 02:23:12 +02:00
BufferProvider : : getDescriptorFor ( size_t storageSize )
2011-09-04 01:54:36 +02:00
{
BufferProvider: re-think through the process of Key creation
...while the implementation provided herein is trivial,
it represents the entrance point into the process covered by the
''Buffer Provider Protocol''; thus I went again through all the
stages of the implementation, and confirmed my analyiss from 2024:
9a23aa773b93b0be8a3d85437f5f267d405bd87c
Today I'd even go so far as to call this a **crietrion of consistency**:
The path leading to the LOCK-transition must be reproducible.
The existing implementation, now re-cast into a new API,
ensures this by requiring an explicitly given Buffer Descriptor
at that point, and ''does not offer any one-step shortcut.''
__The point to note is__: the system used for implementing those type-IDs,
which is a tree of chained hashes, is deliberately open and extensible.
''In theory'' it would be possible thus to arrive at different hash-IDs
for the same criteria, if these are added gradually, in several steps,
as a refinement. This leeway is acceptable, as long as it can not happen
that two competing allocation processes want to lock the same
memory address, but tracked through different parent type-IDs.
2026-02-15 22:26:39 +01:00
auto & typeKey = bufferStage_ - > defineBufferType ( storageSize , TypeHandler : : RAW ) ;
2026-02-16 23:57:12 +01:00
return buildDescriptor ( typeKey ) ;
2011-09-04 01:54:36 +02:00
}
2011-11-12 00:36:53 +01:00
2024-07-15 18:52:59 +02:00
BuffDescr
2011-11-12 00:36:53 +01:00
BufferProvider : : getDescriptorFor ( size_t storageSize , TypeHandler specialTreatment )
{
BufferProvider: re-think through the process of Key creation
...while the implementation provided herein is trivial,
it represents the entrance point into the process covered by the
''Buffer Provider Protocol''; thus I went again through all the
stages of the implementation, and confirmed my analyiss from 2024:
9a23aa773b93b0be8a3d85437f5f267d405bd87c
Today I'd even go so far as to call this a **crietrion of consistency**:
The path leading to the LOCK-transition must be reproducible.
The existing implementation, now re-cast into a new API,
ensures this by requiring an explicitly given Buffer Descriptor
at that point, and ''does not offer any one-step shortcut.''
__The point to note is__: the system used for implementing those type-IDs,
which is a tree of chained hashes, is deliberately open and extensible.
''In theory'' it would be possible thus to arrive at different hash-IDs
for the same criteria, if these are added gradually, in several steps,
as a refinement. This leeway is acceptable, as long as it can not happen
that two competing allocation processes want to lock the same
memory address, but tracked through different parent type-IDs.
2026-02-15 22:26:39 +01:00
auto & typeKey = bufferStage_ - > defineBufferType ( storageSize , move ( specialTreatment ) ) ;
2026-02-16 23:57:12 +01:00
return buildDescriptor ( typeKey ) ;
2011-11-12 00:36:53 +01:00
}
2011-11-14 01:43:29 +01:00
/** BufferProvider API: declare in advance the need for working buffers.
* This optional call allows client code to ensure the availability of the
* necessary working space , prior to starting the actual operations . The
* client may reasonably assume to get the actual number of buffers , as
* indicated by the return value . A provider may be able to handle
* various kinds of buffers ( e . g . of differing size ) , which are
2024-07-15 18:52:59 +02:00
* distinguished by _the type embodied into_ the BuffDescr .
2011-11-14 01:43:29 +01:00
* @ return maximum number of simultaneously usable buffers of this type ,
* to be retrieved later through calls to # lockBuffer .
* @ throw error : : State when no buffer of this kind can be provided
* @ note the returned count may differ from the requested count .
*/
uint
2026-02-12 22:25:32 +01:00
BufferProvider : : announce ( uint cnt , BuffDescr const & type )
2011-11-14 01:43:29 +01:00
{
2026-02-12 22:25:32 +01:00
size_t buffSiz = getBufferSize ( type ) ;
uint actually_possible = bufferStore_ - > prepareBuffers ( cnt , buffSiz , type ) ;
2011-11-14 01:43:29 +01:00
if ( ! actually_possible )
throw error : : State ( " unable to fulfil request for buffers "
, LUMIERA_ERROR_BUFFER_MANAGEMENT ) ;
return actually_possible ;
}
/** BufferProvider API: retrieve a single buffer for exclusive use.
* This call actually claims a buffer of this type and marks it for
2026-02-13 22:43:24 +01:00
* use by client code . Performs the necessary metadata state transition
* leading from an abstract buffer type to a derived metadata : : Entry
* that corresponds to an actual buffer and has a lifecycle state .
* This entry is marked as _locked_ for exclusive use by one client .
* The returned handle allows to query state and perform further
* state transitions ( _emitted_ , _released_ ) , yet provides no
* automatic tracking and clean - up . The client is explicitly
* responsible to invoke # releaseBuffer ( either on the
* BufferProvider , or directly on the BuffHandle ) .
2011-11-14 01:43:29 +01:00
* @ return a copyable handle , representing this buffer and this usage transaction .
* @ throw error : : State when unable to provide this buffer
* @ note this function may be used right away , without prior announcing , but then
* the client should be prepared for exceptions . The # announce operation allows
* to establish a reliably available baseline .
2025-02-03 22:10:10 +01:00
* @ todo 2 / 2025 might need to accept a cache key as additional parameter //////////////////////////////////TICKET #1392 : get cache key from computation to the cache backend
2011-11-14 01:43:29 +01:00
*/
BuffHandle
2024-07-15 18:52:59 +02:00
BufferProvider : : lockBuffer ( BuffDescr const & type )
2011-11-14 01:43:29 +01:00
{
REQUIRE ( was_created_by_this_provider ( type ) ) ;
2026-02-14 23:48:28 +01:00
auto & typeKey = bufferStage_ - > lookup ( type ) ;
auto [ storage , localTag ] = bufferStore_ - > provideBuffer ( typeKey . storageSize ( ) , type , typeKey . localTag ( ) ) ;
auto & stateKey = bufferStage_ - > mark_locked ( typeKey , storage , localTag ) ;
2026-02-13 22:43:24 +01:00
2026-02-16 23:57:12 +01:00
return BuffHandle ( buildDescriptor ( stateKey ) , storage ) ;
2026-02-15 23:39:13 +01:00
} // NOTE: not the underlying parent descriptor!
2011-11-14 01:43:29 +01:00
/** BufferProvider API: state transition to \em emitted state.
* Client code may signal a state transition through this optional operation .
* The actual meaning of an " emitted " buffer is implementation defined ; similarly ,
* some back - ends may actually do something when emitting a buffer ( e . g . commit data
* to cache ) , while others just set a flag or do nothing at all . This state transition
* may be invoked at most once per locked buffer .
* @ throw error : : Fatal in case of invalid state transition sequence . Only a locked buffer
* may be emitted , and at most once .
* @ warning by convention , emitting a buffer implies that the contained data is ready and
* might be used by other parts of the application .
2025-06-07 23:59:57 +02:00
* While an emitted buffer should not be modified anymore , it can still be accessed .
2011-11-14 01:43:29 +01:00
*/
void
2011-11-15 04:47:31 +01:00
BufferProvider : : emitBuffer ( BuffHandle const & handle )
2011-11-14 01:43:29 +01:00
{
2026-02-14 23:48:28 +01:00
auto & stateKey = bufferStage_ - > mark_emitted ( handle ) ;
bufferStore_ - > mark_emitted ( stateKey . storageSize ( ) , stateKey . parentKey ( ) , stateKey . localTag ( ) ) ;
2011-11-14 01:43:29 +01:00
}
2026-02-14 23:48:28 +01:00
/** BufferProvider API: declare buffer usage as completed and detach from storage.
2026-02-12 22:25:32 +01:00
* Client code is required to release _each previously locked buffer_ eventually .
2011-11-14 01:43:29 +01:00
* @ warning invalidates the BuffHandle , clients mustn ' t access the buffer anymore .
* Right after releasing , an access through the handle will throw ;
* yet the buffer might be re - used and the handle become valid
2025-06-07 23:59:57 +02:00
* later on accidentally .
2011-11-14 01:43:29 +01:00
* @ note EX_FREE
*/
void
BufferProvider: reconsider and rearrange the public API
In the end I refrained from applying most of the changes I had intended.
I am aware that `BufferProvider` is still quite a massive structure,
yet with the implementation refactorings done thus far, it seems
to be reasonably clear and self-contained now.
It would be possible to totally overthrow the grown structure and
expose only the two handles (BuffDescr and BuffHandle), together with
a factory function, but I cannot see how this would help to make the
code clearer and more approachable. Maybe it would make the usage
more obvious from the client's perspective — yet, to be honest,
there are not ''that much clients'' to justify such a move.
Furthermore, the implementation is far from finished: for both of
the back-end lines, a fully production-strength implementation
must be created, that is able to operate in a highly concurrent
environment; very likely some lock-free messaging and hand-over
between threads will become necessary, adding to the complexity.
Thus it seems better to note the ''design critique'', but to
postpone any further refactorings to a point where we can watch
a fully developed Render Engine under production load.
2026-02-16 20:50:04 +01:00
BufferProvider : : releaseBuffer ( BuffHandle & handle )
2026-02-14 23:48:28 +01:00
try { // might invoke embedded dtor function
auto & stateKey = bufferStage_ - > mark_released ( handle ) ;
bufferStore_ - > detachBuffer ( stateKey . storageSize ( ) , stateKey . parentKey ( )
, std : : make_tuple ( handle . rawStorage ( ) , stateKey . localTag ( ) ) ) ;
bufferStage_ - > discard ( handle ) ;
2011-11-14 01:43:29 +01:00
}
2011-11-15 04:47:31 +01:00
ERROR_LOG_AND_IGNORE ( engine , " releasing a buffer from BufferProvider " )
2011-11-14 01:43:29 +01:00
2011-11-25 20:23:31 +01:00
/** @internal abort normal lifecycle, reset the underlying buffer and detach from it.
2025-06-07 23:59:57 +02:00
* This allows to break out of normal usage and reset the handle to _invalid state_
2011-11-25 20:23:31 +01:00
* @ param invokeDtor if possibly the clean - up function of an TypeHandler registered with
* the buffer metadata should be invoked prior to resetting the metadata state .
* Default is \ em not to invoke anything
* @ note EX_FREE
*/
void
BufferProvider: reconsider and rearrange the public API
In the end I refrained from applying most of the changes I had intended.
I am aware that `BufferProvider` is still quite a massive structure,
yet with the implementation refactorings done thus far, it seems
to be reasonably clear and self-contained now.
It would be possible to totally overthrow the grown structure and
expose only the two handles (BuffDescr and BuffHandle), together with
a factory function, but I cannot see how this would help to make the
code clearer and more approachable. Maybe it would make the usage
more obvious from the client's perspective — yet, to be honest,
there are not ''that much clients'' to justify such a move.
Furthermore, the implementation is far from finished: for both of
the back-end lines, a fully production-strength implementation
must be created, that is able to operate in a highly concurrent
environment; very likely some lock-free messaging and hand-over
between threads will become necessary, adding to the complexity.
Thus it seems better to note the ''design critique'', but to
postpone any further refactorings to a point where we can watch
a fully developed Render Engine under production load.
2026-02-16 20:50:04 +01:00
BufferProvider : : emergencyCleanup ( BuffHandle & handle , bool invokeDtor )
2011-11-26 00:09:59 +01:00
try {
2026-02-14 23:48:28 +01:00
auto & stateKey = bufferStage_ - > abandon ( handle , invokeDtor ) ;
bufferStore_ - > detachBuffer ( stateKey . storageSize ( ) , stateKey . parentKey ( )
, std : : make_tuple ( handle . rawStorage ( ) , stateKey . localTag ( ) ) ) ;
bufferStage_ - > discard ( handle ) ;
2011-11-25 20:23:31 +01:00
}
2011-11-26 00:09:59 +01:00
ERROR_LOG_AND_IGNORE ( engine , " cleanup of buffer metadata while handling an error " )
2011-11-25 20:23:31 +01:00
2011-11-13 04:20:14 +01:00
2011-09-04 01:54:36 +02:00
2024-07-15 18:52:59 +02:00
/* === BuffDescr and BuffHandle === */
2011-09-04 01:54:36 +02:00
2026-02-16 23:57:12 +01:00
BuffDescr
BufferProvider : : buildDescriptor ( HashVal key )
{
return { * this , key } ;
}
BufferProvider: reconsider and rearrange the public API
In the end I refrained from applying most of the changes I had intended.
I am aware that `BufferProvider` is still quite a massive structure,
yet with the implementation refactorings done thus far, it seems
to be reasonably clear and self-contained now.
It would be possible to totally overthrow the grown structure and
expose only the two handles (BuffDescr and BuffHandle), together with
a factory function, but I cannot see how this would help to make the
code clearer and more approachable. Maybe it would make the usage
more obvious from the client's perspective — yet, to be honest,
there are not ''that much clients'' to justify such a move.
Furthermore, the implementation is far from finished: for both of
the back-end lines, a fully production-strength implementation
must be created, that is able to operate in a highly concurrent
environment; very likely some lock-free messaging and hand-over
between threads will become necessary, adding to the complexity.
Thus it seems better to note the ''design critique'', but to
postpone any further refactorings to a point where we can watch
a fully developed Render Engine under production load.
2026-02-16 20:50:04 +01:00
bool
BufferProvider : : was_created_by_this_provider ( BuffDescr const & descr ) const
{
return isSameAdr ( this , descr . provider_ ) ;
}
2026-02-15 23:39:13 +01:00
/**
* A Buffer Descriptor is considered _valid_
* iff it represents a registered buffer type .
* @ note this implies that the buffer size is not zero .
*/
2011-09-04 01:54:36 +02:00
bool
2026-02-15 23:39:13 +01:00
BuffDescr : : isValid ( ) const
2011-09-04 01:54:36 +02:00
{
2024-07-11 23:35:05 +02:00
ENSURE ( provider_ ) ;
2026-02-16 00:42:23 +01:00
return provider_ - > isValid ( * this ) ;
2026-02-15 23:39:13 +01:00
}
/**
* A concrete Buffer Handle is considered valid ,
2026-02-16 00:42:23 +01:00
* iff it is currently registered in the buffer metadata table ,
* and the corresponding metadata : : Entry indicates LOCKED state ,
* but not yet emitted ( or released ) .
2026-02-15 23:39:13 +01:00
* @ note this implies also that it is in some active state , and
* indirectly ( due to the _Buffer Provider Protocol_ ) also
* that the _parent type_ is valid , which means that it was
* created from a valid BuffDescr . But note that we can not
* see this parent type without lookup by the BufferProvider ;
* The embedded # descriptor_ is synthetic , and reflects the
* handle ' s _state - key_ ( ⟶ registry Entry ) not the type - key .
*/
bool
BuffHandle : : isValid ( ) const
{
ENSURE ( descriptor_ . provider_ ) ;
return bool ( pBuffer_ )
2026-02-16 00:42:23 +01:00
and descriptor_ . provider_ - > isAccessible ( * this ) ;
2011-09-04 01:54:36 +02:00
}
2011-09-19 01:42:37 +02:00
2011-11-21 02:28:44 +01:00
size_t
2026-02-14 16:55:06 +01:00
BuffDescr : : buffSize ( ) const
2011-11-21 02:28:44 +01:00
{
2024-07-11 23:35:05 +02:00
ENSURE ( provider_ ) ;
2011-11-21 02:28:44 +01:00
return provider_ - > getBufferSize ( * this ) ;
}
2026-02-15 23:39:13 +01:00
size_t
BuffHandle : : size ( ) const
{
return descriptor_ . buffSize ( ) ;
}
2011-11-21 02:28:44 +01:00
2024-07-11 23:35:05 +02:00
uint
2024-07-15 18:52:59 +02:00
BuffDescr : : announce ( uint count )
2024-07-11 23:35:05 +02:00
{
ENSURE ( provider_ ) ;
return provider_ - > announce ( count , * this ) ;
}
BuffHandle
2024-07-15 18:52:59 +02:00
BuffDescr : : lockBuffer ( )
2024-07-11 23:35:05 +02:00
{
ENSURE ( provider_ ) ;
return provider_ - > lockBuffer ( * this ) ;
}
2011-11-14 01:43:29 +01:00
void
2011-11-25 18:20:01 +01:00
BuffHandle : : emit ( )
2011-11-14 01:43:29 +01:00
{
2011-11-25 18:20:01 +01:00
REQUIRE ( isValid ( ) ) ;
descriptor_ . provider_ - > emitBuffer ( * this ) ;
2011-11-14 01:43:29 +01:00
}
2011-09-19 01:42:37 +02:00
void
2011-11-25 18:20:01 +01:00
BuffHandle : : release ( )
2011-09-19 01:42:37 +02:00
{
2011-11-25 18:20:01 +01:00
if ( pBuffer_ )
{
REQUIRE ( isValid ( ) ) ;
descriptor_ . provider_ - > releaseBuffer ( * this ) ;
pBuffer_ = 0 ;
}
ENSURE ( ! isValid ( ) ) ;
2011-09-19 01:42:37 +02:00
}
2011-11-20 01:35:52 +01:00
2011-11-25 20:23:31 +01:00
void
BuffHandle : : emergencyCleanup ( )
{
2011-11-26 00:09:59 +01:00
descriptor_ . provider_ - > emergencyCleanup ( * this ) ; // EX_FREE
pBuffer_ = 0 ;
2011-11-25 20:23:31 +01:00
}
2011-11-20 01:35:52 +01:00
2011-12-02 16:10:03 +01:00
} } // namespace engine