// Copyright 2017 The NXT Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "backend/Texture.h" #include "backend/Device.h" #include "common/Assert.h" namespace backend { uint32_t TextureFormatPixelSize(nxt::TextureFormat format) { switch (format) { case nxt::TextureFormat::R8Unorm: case nxt::TextureFormat::R8Uint: return 1; case nxt::TextureFormat::R8G8Unorm: case nxt::TextureFormat::R8G8Uint: return 2; case nxt::TextureFormat::R8G8B8A8Unorm: case nxt::TextureFormat::R8G8B8A8Uint: case nxt::TextureFormat::B8G8R8A8Unorm: return 4; case nxt::TextureFormat::D32FloatS8Uint: return 8; default: UNREACHABLE(); } } bool TextureFormatHasDepth(nxt::TextureFormat format) { switch (format) { case nxt::TextureFormat::D32FloatS8Uint: return true; default: return false; } } bool TextureFormatHasStencil(nxt::TextureFormat format) { switch (format) { case nxt::TextureFormat::D32FloatS8Uint: return true; default: return false; } } bool TextureFormatHasDepthOrStencil(nxt::TextureFormat format) { switch (format) { case nxt::TextureFormat::D32FloatS8Uint: return true; default: return false; } } // TextureBase TextureBase::TextureBase(TextureBuilder* builder) : mDevice(builder->mDevice), mDimension(builder->mDimension), mFormat(builder->mFormat), mWidth(builder->mWidth), mHeight(builder->mHeight), mDepth(builder->mDepth), mNumMipLevels(builder->mNumMipLevels), mAllowedUsage(builder->mAllowedUsage) { } DeviceBase* TextureBase::GetDevice() const { return mDevice; } nxt::TextureDimension TextureBase::GetDimension() const { return mDimension; } nxt::TextureFormat TextureBase::GetFormat() const { return mFormat; } uint32_t TextureBase::GetWidth() const { return mWidth; } uint32_t TextureBase::GetHeight() const { return mHeight; } uint32_t TextureBase::GetDepth() const { return mDepth; } uint32_t TextureBase::GetNumMipLevels() const { return mNumMipLevels; } nxt::TextureUsageBit TextureBase::GetAllowedUsage() const { return mAllowedUsage; } TextureViewBuilder* TextureBase::CreateTextureViewBuilder() { return new TextureViewBuilder(mDevice, this); } // TextureBuilder enum TextureSetProperties { TEXTURE_PROPERTY_DIMENSION = 0x1, TEXTURE_PROPERTY_EXTENT = 0x2, TEXTURE_PROPERTY_FORMAT = 0x4, TEXTURE_PROPERTY_MIP_LEVELS = 0x8, TEXTURE_PROPERTY_ALLOWED_USAGE = 0x10, }; TextureBuilder::TextureBuilder(DeviceBase* device) : Builder(device) { } TextureBase* TextureBuilder::GetResultImpl() { constexpr int allProperties = TEXTURE_PROPERTY_DIMENSION | TEXTURE_PROPERTY_EXTENT | TEXTURE_PROPERTY_FORMAT | TEXTURE_PROPERTY_MIP_LEVELS | TEXTURE_PROPERTY_ALLOWED_USAGE; if ((mPropertiesSet & allProperties) != allProperties) { HandleError("Texture missing properties"); return nullptr; } // TODO(cwallez@chromium.org): check stuff based on the dimension return mDevice->CreateTexture(this); } void TextureBuilder::SetDimension(nxt::TextureDimension dimension) { if ((mPropertiesSet & TEXTURE_PROPERTY_DIMENSION) != 0) { HandleError("Texture dimension property set multiple times"); return; } mPropertiesSet |= TEXTURE_PROPERTY_DIMENSION; mDimension = dimension; } void TextureBuilder::SetExtent(uint32_t width, uint32_t height, uint32_t depth) { if ((mPropertiesSet & TEXTURE_PROPERTY_EXTENT) != 0) { HandleError("Texture extent property set multiple times"); return; } if (width == 0 || height == 0 || depth == 0) { HandleError("Cannot create an empty texture"); return; } mPropertiesSet |= TEXTURE_PROPERTY_EXTENT; mWidth = width; mHeight = height; mDepth = depth; } void TextureBuilder::SetFormat(nxt::TextureFormat format) { if ((mPropertiesSet & TEXTURE_PROPERTY_FORMAT) != 0) { HandleError("Texture format property set multiple times"); return; } mPropertiesSet |= TEXTURE_PROPERTY_FORMAT; mFormat = format; } void TextureBuilder::SetMipLevels(uint32_t numMipLevels) { if ((mPropertiesSet & TEXTURE_PROPERTY_MIP_LEVELS) != 0) { HandleError("Texture mip levels property set multiple times"); return; } mPropertiesSet |= TEXTURE_PROPERTY_MIP_LEVELS; mNumMipLevels = numMipLevels; } void TextureBuilder::SetAllowedUsage(nxt::TextureUsageBit usage) { if ((mPropertiesSet & TEXTURE_PROPERTY_ALLOWED_USAGE) != 0) { HandleError("Texture allowed usage property set multiple times"); return; } mPropertiesSet |= TEXTURE_PROPERTY_ALLOWED_USAGE; mAllowedUsage = usage; } // TextureViewBase TextureViewBase::TextureViewBase(TextureViewBuilder* builder) : mTexture(builder->mTexture) { } const TextureBase* TextureViewBase::GetTexture() const { return mTexture.Get(); } TextureBase* TextureViewBase::GetTexture() { return mTexture.Get(); } // TextureViewBuilder TextureViewBuilder::TextureViewBuilder(DeviceBase* device, TextureBase* texture) : Builder(device), mTexture(texture) { } TextureViewBase* TextureViewBuilder::GetResultImpl() { return mDevice->CreateTextureView(this); } } // namespace backend