#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2013 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_GRAPHICS_SOURCE 1 #include "Nuclex/Graphics/Rasterization/Buffer.h" #include #include #include #undef min #undef max namespace Nuclex { namespace Graphics { namespace Rasterization { // ------------------------------------------------------------------------------------------- // Buffer::Buffer(std::size_t capacityInBytes) : CapacityBytes(capacityInBytes), usedBytes(0), firstChangeOffset(0), lastChangeOffset(0), Contents(new std::uint8_t[capacityInBytes]) {} // ------------------------------------------------------------------------------------------- // Buffer::Buffer(const Buffer &other) : CapacityBytes(other.CapacityBytes), usedBytes(other.usedBytes), firstChangeOffset(0), lastChangeOffset(0), Contents(new std::uint8_t[this->CapacityBytes]) { std::copy_n(other.Contents, this->usedBytes, this->Contents); } // ------------------------------------------------------------------------------------------- // Buffer::~Buffer() { delete []this->Contents; } // ------------------------------------------------------------------------------------------- // void Buffer::SuppressChangeNotifications() { this->firstChangeOffset = static_cast(-1); this->lastChangeOffset = 0; } // ------------------------------------------------------------------------------------------- // void Buffer::PermitChangeNotifications() { std::size_t firstChangeOffset = this->firstChangeOffset; std::size_t lastChangeOffset = this->lastChangeOffset; this->firstChangeOffset = 0; this->lastChangeOffset = 0; if(firstChangeOffset < lastChangeOffset) { OnChanged(firstChangeOffset, lastChangeOffset); } } // ------------------------------------------------------------------------------------------- // Buffer::Observer *Buffer::GetObserver(const void *owner) const { return this->observers.Get(owner); } // ------------------------------------------------------------------------------------------- // void Buffer::AttachObserver(const void *owner, Observer *observer) { using namespace std; bool wasUnique = this->observers.AttachUnique(owner, observer); // Observer management should be accurate and error-free! assert(wasUnique && "Only one observer can be attached per owner"); wasUnique; // avoid unreferenced parameter warning } // ------------------------------------------------------------------------------------------- // void Buffer::DetachObserver(const void *owner) { using namespace std; bool wasAttached = this->observers.Detach(owner); // Observer management should be accurate and error-free! assert(wasAttached && "Attempted to detach an observer that was not attached"); wasAttached; // avoid unreferenced parameter warning } // ------------------------------------------------------------------------------------------- // Buffer &Buffer::operator =(const Buffer &other) { if(other.usedBytes > this->CapacityBytes) { throw std::runtime_error("Other buffer is too large for this buffer's capacity"); } std::copy_n(other.Contents, this->usedBytes, this->Contents); this->usedBytes = other.usedBytes; OnChanged(0, this->usedBytes); return *this; } // ------------------------------------------------------------------------------------------- // void Buffer::OnDestroying() { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->Destroying(); } } // ------------------------------------------------------------------------------------------- // void Buffer::OnCleared() { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->Cleared(); } } // ------------------------------------------------------------------------------------------- // void Buffer::OnChanged(std::size_t offset, std::size_t count) { std::size_t lastOffset = offset + count; if(this->firstChangeOffset == this->lastChangeOffset) { std::vector copy = this->observers.Copy(); for(std::size_t index = 0; index < copy.size(); ++index) { copy[index]->Changed(offset, count); } } else { // Change notifications are currently suppressed this->firstChangeOffset = std::min(offset, this->firstChangeOffset); this->lastChangeOffset = std::max(lastOffset, this->lastChangeOffset); } this->usedBytes = std::max(this->usedBytes, lastOffset); } // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Graphics::Rasterization