summaryrefslogtreecommitdiffstats
path: root/o3d/core
diff options
context:
space:
mode:
authorrlp@google.com <rlp@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-28 22:45:01 +0000
committerrlp@google.com <rlp@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-28 22:45:01 +0000
commit02525bc37fe1722c8b38af1d6087bf286e075bf9 (patch)
treeecb6e9b67b7745cf14a7574b331525346b5e638c /o3d/core
parent139dd55c937dbad1224571ddca0d13d9e723af0f (diff)
downloadchromium_src-02525bc37fe1722c8b38af1d6087bf286e075bf9.zip
chromium_src-02525bc37fe1722c8b38af1d6087bf286e075bf9.tar.gz
chromium_src-02525bc37fe1722c8b38af1d6087bf286e075bf9.tar.bz2
Adding in render surfaces for command buffers. Fixing SetRect as well.
Review URL: http://codereview.chromium.org/160401 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24825 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/core')
-rw-r--r--o3d/core/build.scons1
-rw-r--r--o3d/core/cross/command_buffer/render_surface_cb.cc118
-rw-r--r--o3d/core/cross/command_buffer/render_surface_cb.h94
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.cc23
-rw-r--r--o3d/core/cross/command_buffer/renderer_cb.h14
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.cc262
-rw-r--r--o3d/core/cross/command_buffer/texture_cb.h5
-rw-r--r--o3d/core/cross/render_surface_test.cc227
-rw-r--r--o3d/core/cross/renderer.h5
9 files changed, 707 insertions, 42 deletions
diff --git a/o3d/core/build.scons b/o3d/core/build.scons
index 4e5034e..9d01a37 100644
--- a/o3d/core/build.scons
+++ b/o3d/core/build.scons
@@ -181,6 +181,7 @@ elif 'RENDERER_CB' in env['CPPDEFINES'] :
'cross/command_buffer/param_cache_cb.cc',
'cross/command_buffer/primitive_cb.cc',
'cross/command_buffer/renderer_cb.cc',
+ 'cross/command_buffer/render_surface_cb.cc',
'cross/command_buffer/sampler_cb.cc',
'cross/command_buffer/states_cb.cc',
'cross/command_buffer/stream_bank_cb.cc',
diff --git a/o3d/core/cross/command_buffer/render_surface_cb.cc b/o3d/core/cross/command_buffer/render_surface_cb.cc
new file mode 100644
index 0000000..0f57536e
--- /dev/null
+++ b/o3d/core/cross/command_buffer/render_surface_cb.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "core/cross/command_buffer/render_surface_cb.h"
+#include "command_buffer/client/cross/cmd_buffer_helper.h"
+
+namespace o3d {
+
+using command_buffer::ResourceID;
+using command_buffer::CommandBufferEntry;
+using command_buffer::CommandBufferHelper;
+namespace create_render_surface_cmd = command_buffer::create_render_surface_cmd;
+
+RenderSurfaceCB::RenderSurfaceCB(ServiceLocator *service_locator,
+ int width,
+ int height,
+ int mip_level,
+ int side,
+ Texture *texture,
+ RendererCB *renderer)
+ : RenderSurface(service_locator, width, height, texture),
+ resource_id_(command_buffer::kInvalidResource),
+ renderer_(renderer) {
+ DCHECK(texture);
+
+ ResourceID id = renderer_->render_surface_ids().AllocateID();
+ resource_id_ = id;
+ CommandBufferHelper *helper = renderer_->helper();
+ CommandBufferEntry args[4];
+ args[0].value_uint32 = id;
+ args[1].value_uint32 =
+ create_render_surface_cmd::Width::MakeValue(width) |
+ create_render_surface_cmd::Height::MakeValue(height);
+ args[2].value_uint32 =
+ create_render_surface_cmd::Levels::MakeValue(mip_level) |
+ create_render_surface_cmd::Side::MakeValue(side);
+ args[3].value_uint32 =
+ reinterpret_cast<ResourceID>(texture->GetTextureHandle());
+ helper->AddCommand(command_buffer::CREATE_RENDER_SURFACE, 4, args);
+}
+
+RenderSurfaceCB::~RenderSurfaceCB() {
+ Destroy();
+}
+
+void RenderSurfaceCB::Destroy() {
+ // This should never get called during rendering.
+ if (resource_id_ != command_buffer::kInvalidResource) {
+ CommandBufferHelper *helper = renderer_->helper();
+ CommandBufferEntry args[1];
+ args[0].value_uint32 = resource_id_;
+ helper->AddCommand(command_buffer::DESTROY_RENDER_SURFACE, 1, args);
+ renderer_->render_surface_ids().FreeID(resource_id_);
+ resource_id_ = command_buffer::kInvalidResource;
+ }
+}
+
+RenderDepthStencilSurfaceCB::RenderDepthStencilSurfaceCB(
+ ServiceLocator *service_locator,
+ int width,
+ int height,
+ RendererCB *renderer)
+ : RenderDepthStencilSurface(service_locator, width, height),
+ resource_id_(command_buffer::kInvalidResource),
+ renderer_(renderer) {
+ ResourceID id = renderer_->depth_surface_ids().AllocateID();
+ resource_id_ = id;
+ CommandBufferHelper *helper = renderer_->helper();
+ CommandBufferEntry args[2];
+ args[0].value_uint32 = id;
+ args[1].value_uint32 =
+ create_render_surface_cmd::Width::MakeValue(width) |
+ create_render_surface_cmd::Height::MakeValue(height);
+ helper->AddCommand(command_buffer::CREATE_DEPTH_SURFACE, 2, args);
+}
+
+void RenderDepthStencilSurfaceCB::Destroy() {
+ if (resource_id_ != command_buffer::kInvalidResource) {
+ CommandBufferHelper *helper = renderer_->helper();
+ CommandBufferEntry args[1];
+ args[0].value_uint32 = resource_id_;
+ helper->AddCommand(command_buffer::DESTROY_DEPTH_SURFACE, 1, args);
+ renderer_->depth_surface_ids().FreeID(resource_id_);
+ resource_id_ = command_buffer::kInvalidResource;
+ }
+}
+
+} // namespace o3d
+
diff --git a/o3d/core/cross/command_buffer/render_surface_cb.h b/o3d/core/cross/command_buffer/render_surface_cb.h
new file mode 100644
index 0000000..76581ac
--- /dev/null
+++ b/o3d/core/cross/command_buffer/render_surface_cb.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef O3D_CORE_CROSS_COMMAND_BUFFER_RENDER_SURFACE_CB_H_
+#define O3D_CORE_CROSS_COMMAND_BUFFER_RENDER_SURFACE_CB_H_
+
+#include "core/cross/render_surface.h"
+#include "core/cross/command_buffer/renderer_cb.h"
+#include "command_buffer/common/cross/resource.h"
+
+namespace o3d {
+
+class RenderSurfaceCB : public RenderSurface {
+ public:
+ typedef SmartPointer<RenderSurfaceCB> Ref;
+
+ RenderSurfaceCB(ServiceLocator *service_locator,
+ int width,
+ int height,
+ int mip_level,
+ int side,
+ Texture *texture,
+ RendererCB *renderer);
+ virtual ~RenderSurfaceCB();
+
+ virtual Bitmap::Ref PlatformSpecificGetBitmap() const {
+ // TODO(rlp): Add this functionality.
+ DCHECK(false);
+ return Bitmap::Ref();
+ }
+
+ virtual void Destroy();
+
+ // Gets the render surface resource ID.
+ command_buffer::ResourceID resource_id() const { return resource_id_; }
+ private:
+ command_buffer::ResourceID resource_id_;
+ RendererCB* renderer_;
+ DISALLOW_COPY_AND_ASSIGN(RenderSurfaceCB);
+};
+
+class RenderDepthStencilSurfaceCB : public RenderDepthStencilSurface {
+ public:
+ typedef SmartPointer<RenderDepthStencilSurfaceCB> Ref;
+
+ RenderDepthStencilSurfaceCB(ServiceLocator *service_locator,
+ int width,
+ int height,
+ RendererCB *renderer);
+ virtual ~RenderDepthStencilSurfaceCB() {}
+
+ virtual void Destroy();
+
+ // Gets the render depth stencil surface resource ID.
+ command_buffer::ResourceID resource_id() const { return resource_id_; }
+ private:
+ command_buffer::ResourceID resource_id_;
+ RendererCB* renderer_;
+ DISALLOW_COPY_AND_ASSIGN(RenderDepthStencilSurfaceCB);
+};
+
+} // namespace o3d
+
+#endif // O3D_CORE_CROSS_COMMAND_BUFFER_RENDER_SURFACE_CB_H_
+
diff --git a/o3d/core/cross/command_buffer/renderer_cb.cc b/o3d/core/cross/command_buffer/renderer_cb.cc
index 3b00ef2..4272c83 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.cc
+++ b/o3d/core/cross/command_buffer/renderer_cb.cc
@@ -42,6 +42,7 @@
#include "core/cross/command_buffer/param_cache_cb.h"
#include "core/cross/command_buffer/primitive_cb.h"
#include "core/cross/command_buffer/renderer_cb.h"
+#include "core/cross/command_buffer/render_surface_cb.h"
#include "core/cross/command_buffer/sampler_cb.h"
#include "core/cross/command_buffer/states_cb.h"
#include "core/cross/command_buffer/stream_bank_cb.h"
@@ -226,11 +227,18 @@ void RendererCB::PlatformSpecificPresent() {
void RendererCB::SetRenderSurfacesPlatformSpecific(
const RenderSurface* surface,
const RenderDepthStencilSurface* surface_depth) {
- // TODO: Provide an implementation for this routine.
+ const RenderSurfaceCB* surface_cb =
+ down_cast<const RenderSurfaceCB*>(surface);
+ const RenderDepthStencilSurfaceCB* surface_depth_cb =
+ down_cast<const RenderDepthStencilSurfaceCB*>(surface_depth);
+ command_buffer::CommandBufferEntry args[2];
+ args[0].value_uint32 = surface_cb->resource_id();
+ args[1].value_uint32 = surface_depth_cb->resource_id();
+ helper_->AddCommand(command_buffer::SET_RENDER_SURFACE, 2, args);
}
void RendererCB::SetBackBufferPlatformSpecific() {
- // TODO: Provide an implementation for this routine.
+ helper_->AddCommand(command_buffer::SET_BACK_SURFACES, 0, NULL);
}
// Creates a StreamBank, returning a platform specific implementation class.
@@ -326,4 +334,15 @@ const int* RendererCB::GetRGBAUByteNSwizzleTable() {
Renderer* Renderer::CreateDefaultRenderer(ServiceLocator* service_locator) {
return RendererCB::CreateDefault(service_locator);
}
+
+// Creates and returns a platform specific RenderDepthStencilSurface object.
+RenderDepthStencilSurface::Ref RendererCB::CreateDepthStencilSurface(
+ int width,
+ int height) {
+ return RenderDepthStencilSurface::Ref(
+ new RenderDepthStencilSurfaceCB(service_locator(),
+ width,
+ height,
+ this));
+}
} // namespace o3d
diff --git a/o3d/core/cross/command_buffer/renderer_cb.h b/o3d/core/cross/command_buffer/renderer_cb.h
index 666c493..6a12c72 100644
--- a/o3d/core/cross/command_buffer/renderer_cb.h
+++ b/o3d/core/cross/command_buffer/renderer_cb.h
@@ -101,12 +101,10 @@ class RendererCB : public Renderer {
// Creates and returns a platform specific Sampler object.
virtual Sampler::Ref CreateSampler();
- // TODO: Fill this in
+ // Creates and returns a platform specific RenderDepthStencilSurface object.
virtual RenderDepthStencilSurface::Ref CreateDepthStencilSurface(
int width,
- int height) {
- return RenderDepthStencilSurface::Ref();
- }
+ int height);
// Gets the allocator for vertex buffer IDs.
IdAllocator &vertex_buffer_ids() { return vertex_buffer_ids_; }
@@ -129,6 +127,12 @@ class RendererCB : public Renderer {
// Gets the allocator for sampler IDs.
IdAllocator &sampler_ids() { return sampler_ids_; }
+ // Gets the allocator for render surfaces IDs.
+ IdAllocator &render_surface_ids() { return render_surface_ids_; }
+
+ // Gets the allocator for depth stencil surfaces IDs.
+ IdAllocator &depth_surface_ids() { return depth_surface_ids_; }
+
// Gets the command buffer helper.
command_buffer::CommandBufferHelper *helper() const { return helper_; }
@@ -237,6 +241,8 @@ class RendererCB : public Renderer {
IdAllocator effect_param_ids_;
IdAllocator texture_ids_;
IdAllocator sampler_ids_;
+ IdAllocator render_surface_ids_;
+ IdAllocator depth_surface_ids_;
unsigned int frame_token_;
class StateManager;
diff --git a/o3d/core/cross/command_buffer/texture_cb.cc b/o3d/core/cross/command_buffer/texture_cb.cc
index bfa8684..e01e1ce 100644
--- a/o3d/core/cross/command_buffer/texture_cb.cc
+++ b/o3d/core/cross/command_buffer/texture_cb.cc
@@ -33,7 +33,6 @@
// Implementations of the abstract Texture2D and TextureCUBE classes using
// the OpenCB graphics API.
-#include "core/cross/precompile.h"
#include "core/cross/error.h"
#include "core/cross/types.h"
#include "core/cross/command_buffer/renderer_cb.h"
@@ -97,6 +96,62 @@ COMPILE_ASSERT(TextureCUBE::FACE_POSITIVE_Z == texture::FACE_POSITIVE_Z,
COMPILE_ASSERT(TextureCUBE::FACE_NEGATIVE_Z == texture::FACE_NEGATIVE_Z,
FACE_NEGATIVE_Z_enums_don_t_match);
+// Writes the data information into a buffer to be sent to the server side.
+void SetTextureDataBuffer(Texture::Format format,
+ const void* src_data,
+ int src_pitch,
+ unsigned src_width,
+ unsigned src_height,
+ void* dst_buffer,
+ unsigned int dst_pitch) {
+ const uint8* src = static_cast<const uint8*>(src_data);
+ uint8* dst = static_cast<uint8*>(dst_buffer);
+ size_t bytes_per_line = image::ComputePitch(format, src_width);
+ for (unsigned yy = 0; yy < src_height; ++yy) {
+ memcpy(dst, src, bytes_per_line);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+}
+// Sends the SET_TEXTURE_DATA command after formatting the args properly.
+void SetTextureData(RendererCB *renderer,
+ ResourceID texture_id,
+ unsigned int x,
+ unsigned int y,
+ unsigned int mip_width,
+ unsigned int mip_height,
+ unsigned int z,
+ unsigned int depth,
+ unsigned int level,
+ TextureCUBE::CubeFace face,
+ int pitch,
+ size_t mip_size,
+ unsigned char* mip_data) {
+ FencedAllocatorWrapper *allocator = renderer->allocator();
+ CommandBufferHelper *helper = renderer->helper();
+
+ CommandBufferEntry args[10];
+ args[0].value_uint32 = texture_id;
+ args[1].value_uint32 =
+ set_texture_data_cmd::X::MakeValue(x) |
+ set_texture_data_cmd::Y::MakeValue(y);
+ args[2].value_uint32 =
+ set_texture_data_cmd::Width::MakeValue(mip_width) |
+ set_texture_data_cmd::Height::MakeValue(mip_height);
+ args[3].value_uint32 =
+ set_texture_data_cmd::Z::MakeValue(z) |
+ set_texture_data_cmd::Depth::MakeValue(depth);
+ args[4].value_uint32 =
+ set_texture_data_cmd::Level::MakeValue(level) |
+ set_texture_data_cmd::Face::MakeValue(face);
+ args[5].value_uint32 = pitch;
+ args[6].value_uint32 = 0; // slice_pitch
+ args[7].value_uint32 = mip_size;
+ args[8].value_uint32 = renderer->transfer_shm_id();
+ args[9].value_uint32 = allocator->GetOffset(mip_data);
+ helper->AddCommand(command_buffer::SET_TEXTURE_DATA, 10, args);
+ allocator->FreePendingToken(mip_data, helper->InsertToken());
+}
// Updates a command buffer texture resource from a bitmap, rescaling if
// necessary.
void UpdateResourceFromBitmap(RendererCB *renderer,
@@ -118,28 +173,19 @@ void UpdateResourceFromBitmap(RendererCB *renderer,
mip_data = buffer;
size_t pitch = image::ComputeBufferSize(mip_width, 1, bitmap.format());
-
- CommandBufferEntry args[10];
- args[0].value_uint32 = texture_id;
- args[1].value_uint32 =
- set_texture_data_cmd::X::MakeValue(0) |
- set_texture_data_cmd::Y::MakeValue(0);
- args[2].value_uint32 =
- set_texture_data_cmd::Width::MakeValue(mip_width) |
- set_texture_data_cmd::Height::MakeValue(mip_height);
- args[3].value_uint32 =
- set_texture_data_cmd::Z::MakeValue(0) |
- set_texture_data_cmd::Depth::MakeValue(1);
- args[4].value_uint32 =
- set_texture_data_cmd::Level::MakeValue(level) |
- set_texture_data_cmd::Face::MakeValue(face);
- args[5].value_uint32 = pitch;
- args[6].value_uint32 = 0; // slice_pitch
- args[7].value_uint32 = mip_size;
- args[8].value_uint32 = renderer->transfer_shm_id();
- args[9].value_uint32 = allocator->GetOffset(mip_data);
- helper->AddCommand(command_buffer::SET_TEXTURE_DATA, 10, args);
- allocator->FreePendingToken(mip_data, helper->InsertToken());
+ SetTextureData(renderer,
+ texture_id,
+ 0,
+ 0,
+ mip_width,
+ mip_height,
+ 0,
+ 1,
+ level,
+ face,
+ pitch,
+ mip_size,
+ mip_data);
}
// Copies back texture resource data into a bitmap.
@@ -255,7 +301,7 @@ Texture2DCB* Texture2DCB::Create(ServiceLocator* service_locator,
args[2].value_uint32 =
create_texture_2d_cmd::Levels::MakeValue(levels) |
create_texture_2d_cmd::Format::MakeValue(cb_format) |
- create_texture_2d_cmd::Flags::MakeValue(0);
+ create_texture_2d_cmd::Flags::MakeValue(enable_render_surfaces);
renderer->helper()->AddCommand(command_buffer::CREATE_TEXTURE_2D, 3, args);
Texture2DCB *texture = new Texture2DCB(service_locator, texture_id,
@@ -272,8 +318,61 @@ void Texture2DCB::SetRect(int level,
unsigned src_height,
const void* src_data,
int src_pitch) {
- // TODO(gman): Someone needs to implement this.
- DCHECK(false);
+ if (level >= levels() || level < 0) {
+ O3D_ERROR(service_locator())
+ << "Trying to SetRect on non-existent level " << level
+ << " on Texture \"" << name() << "\"";
+ return;
+ }
+ if (render_surfaces_enabled()) {
+ O3D_ERROR(service_locator())
+ << "Attempting to SetRect a render-target texture: " << name();
+ return;
+ }
+
+ unsigned mip_width = image::ComputeMipDimension(level, width());
+ unsigned mip_height = image::ComputeMipDimension(level, height());
+
+ if (dst_left + src_width > mip_width ||
+ dst_top + src_height > mip_height) {
+ O3D_ERROR(service_locator())
+ << "SetRect(" << level << ", " << dst_left << ", " << dst_top << ", "
+ << src_width << ", " << src_height << ") out of range for texture << \""
+ << name() << "\"";
+ return;
+ }
+
+ bool entire_rect = dst_left == 0 && dst_top == 0 &&
+ src_width == mip_width && src_height == mip_height;
+ bool compressed = IsCompressed();
+
+ if (compressed && !entire_rect) {
+ O3D_ERROR(service_locator())
+ << "SetRect must be full rectangle for compressed textures";
+ return;
+ }
+ unsigned int dst_pitch = image::ComputePitch(format(), src_width);
+ size_t size = dst_pitch * src_height;
+
+ FencedAllocatorWrapper *allocator = renderer_->allocator();
+ uint8 *buffer = allocator->AllocTyped<uint8>(size);
+ DCHECK(buffer);
+ SetTextureDataBuffer(format(), src_data, src_pitch, src_width, src_height,
+ buffer, dst_pitch);
+
+ SetTextureData(renderer_,
+ resource_id(),
+ dst_left,
+ dst_top,
+ src_width,
+ src_height,
+ 0,
+ 1,
+ level,
+ TextureCUBE::CubeFace(0),
+ dst_pitch,
+ size,
+ buffer);
}
// Locks the given mipmap level of this texture for loading from main memory,
@@ -356,8 +455,26 @@ bool Texture2DCB::Unlock(int level) {
RenderSurface::Ref Texture2DCB::PlatformSpecificGetRenderSurface(
int mip_level) {
DCHECK_LT(mip_level, levels());
- // TODO: Provide an implementation for render surface extraction.
- return RenderSurface::Ref(NULL);
+ if (!render_surfaces_enabled()) {
+ O3D_ERROR(service_locator())
+ << "Attempting to get RenderSurface from non-render-surface-enabled"
+ << " Texture: " << name();
+ return RenderSurface::Ref(NULL);
+ }
+ if (mip_level >= levels() || mip_level < 0) {
+ O3D_ERROR(service_locator())
+ << "Attempting to access non-existent mip_level " << mip_level
+ << " in render-target texture \"" << name() << "\".";
+ return RenderSurface::Ref(NULL);
+ }
+
+ return RenderSurface::Ref(new RenderSurfaceCB(service_locator(),
+ width() >> mip_level,
+ height() >> mip_level,
+ mip_level,
+ 0,
+ this,
+ renderer_));
}
const Texture::RGBASwizzleIndices& Texture2DCB::GetABGR32FSwizzleIndices() {
@@ -422,7 +539,7 @@ TextureCUBECB* TextureCUBECB::Create(ServiceLocator* service_locator,
args[2].value_uint32 =
create_texture_cube_cmd::Levels::MakeValue(levels) |
create_texture_cube_cmd::Format::MakeValue(cb_format) |
- create_texture_cube_cmd::Flags::MakeValue(0);
+ create_texture_cube_cmd::Flags::MakeValue(enable_render_surfaces);
renderer->helper()->AddCommand(command_buffer::CREATE_TEXTURE_CUBE, 3, args);
TextureCUBECB* texture =
@@ -440,8 +557,68 @@ void TextureCUBECB::SetRect(TextureCUBE::CubeFace face,
unsigned src_height,
const void* src_data,
int src_pitch) {
- // TODO(gman): Someone needs to implement this.
- DCHECK(false);
+ if (static_cast<int>(face) < 0 || static_cast<int>(face) >= NUMBER_OF_FACES) {
+ O3D_ERROR(service_locator())
+ << "Trying to SetRect invalid face " << face << " on Texture \""
+ << name() << "\"";
+ return;
+ }
+ if (level >= levels() || level < 0) {
+ O3D_ERROR(service_locator())
+ << "Trying to SetRect non-existent level " << level
+ << " on Texture \"" << name() << "\"";
+ return;
+ }
+ if (render_surfaces_enabled()) {
+ O3D_ERROR(service_locator())
+ << "Attempting to SetRect a render-target texture: " << name();
+ return;
+ }
+
+ unsigned mip_width = image::ComputeMipDimension(level, edge_length());
+ unsigned mip_height = mip_width;
+
+ if (dst_left + src_width > mip_width ||
+ dst_top + src_height > mip_height) {
+ O3D_ERROR(service_locator())
+ << "SetRect(" << level << ", " << dst_left << ", " << dst_top << ", "
+ << src_width << ", " << src_height << ") out of range for texture << \""
+ << name() << "\"";
+ return;
+ }
+
+ bool entire_rect = dst_left == 0 && dst_top == 0 &&
+ src_width == mip_width && src_height == mip_height;
+ bool compressed = IsCompressed();
+
+ if (compressed && !entire_rect) {
+ O3D_ERROR(service_locator())
+ << "SetRect must be full rectangle for compressed textures";
+ return;
+ }
+
+ unsigned int dst_pitch = image::ComputePitch(format(), src_width);
+ size_t size = dst_pitch * src_height;
+
+ FencedAllocatorWrapper *allocator = renderer_->allocator();
+ uint8 *buffer = allocator->AllocTyped<uint8>(size);
+ DCHECK(buffer);
+ SetTextureDataBuffer(format(), src_data, src_pitch, src_width, src_height,
+ buffer, dst_pitch);
+
+ SetTextureData(renderer_,
+ resource_id(),
+ dst_left,
+ dst_top,
+ src_width,
+ src_height,
+ 0,
+ 1,
+ level,
+ face,
+ dst_pitch,
+ size,
+ buffer);
}
// Locks the given face and mipmap level of this texture for loading from
@@ -527,8 +704,27 @@ RenderSurface::Ref TextureCUBECB::PlatformSpecificGetRenderSurface(
TextureCUBE::CubeFace face,
int mip_level) {
DCHECK_LT(mip_level, levels());
- // TODO: Provide an implementation for render surface extraction.
- return RenderSurface::Ref(NULL);
+ if (!render_surfaces_enabled()) {
+ O3D_ERROR(service_locator())
+ << "Attempting to get RenderSurface from non-render-surface-enabled"
+ << " Texture: " << name();
+ return RenderSurface::Ref(NULL);
+ }
+ if (mip_level >= levels() || mip_level < 0) {
+ O3D_ERROR(service_locator())
+ << "Attempting to access non-existent mip_level " << mip_level
+ << " in render-target texture \"" << name() << "\".";
+ return RenderSurface::Ref(NULL);
+ }
+
+ int edge = edge_length() >> mip_level;
+ return RenderSurface::Ref(new RenderSurfaceCB(service_locator(),
+ edge,
+ edge,
+ mip_level,
+ face,
+ this,
+ renderer_));
}
const Texture::RGBASwizzleIndices& TextureCUBECB::GetABGR32FSwizzleIndices() {
diff --git a/o3d/core/cross/command_buffer/texture_cb.h b/o3d/core/cross/command_buffer/texture_cb.h
index c2aa224..3f1b812 100644
--- a/o3d/core/cross/command_buffer/texture_cb.h
+++ b/o3d/core/cross/command_buffer/texture_cb.h
@@ -35,13 +35,12 @@
#ifndef O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H_
#define O3D_CORE_CROSS_COMMAND_BUFFER_TEXTURE_CB_H_
-// Precompiled header comes before everything else.
-#include "core/cross/precompile.h"
-
+#include <vector>
#include "core/cross/bitmap.h"
#include "core/cross/texture.h"
#include "core/cross/types.h"
#include "command_buffer/common/cross/resource.h"
+#include "core/cross/command_buffer/render_surface_cb.h"
namespace o3d {
diff --git a/o3d/core/cross/render_surface_test.cc b/o3d/core/cross/render_surface_test.cc
new file mode 100644
index 0000000..a7b1ba1
--- /dev/null
+++ b/o3d/core/cross/render_surface_test.cc
@@ -0,0 +1,227 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "core/cross/precompile.h"
+#include "tests/common/win/testing_common.h"
+#include "core/cross/client.h"
+#include "core/cross/pack.h"
+#include "core/cross/renderer.h"
+#include "core/cross/bitmap.h"
+#include "core/cross/features.h"
+#include "core/cross/texture.h"
+#include "core/cross/render_surface.h"
+#include "core/cross/render_surface_set.h"
+#include "core/cross/renderer_platform.h"
+
+// Defined in testing_common.cc, for each platform.
+extern o3d::DisplayWindow* g_display_window;
+
+namespace o3d {
+
+class MockRenderer {
+ public:
+ explicit MockRenderer(Renderer* renderer)
+ : renderer_(renderer) {}
+ virtual ~MockRenderer() {}
+
+ void StartRendering() {
+ renderer_->set_rendering(true);
+ }
+ void FinishRendering() {
+ renderer_->set_rendering(false);
+ }
+ void SetRenderSurfaces(const RenderSurface* surface,
+ const RenderDepthStencilSurface* depth_surface) {
+ renderer_->SetRenderSurfaces(surface, depth_surface);
+ }
+ void GetRenderSurfaces(const RenderSurface** surface,
+ const RenderDepthStencilSurface** depth_surface) {
+ renderer_->GetRenderSurfaces(surface, depth_surface);
+ }
+ private:
+ Renderer* renderer_;
+};
+
+class RenderSurfaceTest : public testing::Test {
+ public:
+ RenderSurfaceTest()
+ : object_manager_(g_service_locator) {}
+
+ ServiceLocator* service_locator() {
+ return service_locator_;
+ }
+
+ MockRenderer* renderer() {
+ return renderer_;
+ }
+
+ protected:
+ virtual void SetUp() {
+ service_locator_ = new ServiceLocator;
+ features_ = new Features(service_locator_);
+ pack_ = object_manager_->CreatePack();
+ renderer_ = new MockRenderer(g_renderer);
+ renderer_->StartRendering();
+ }
+
+ virtual void TearDown() {
+ renderer_->FinishRendering();
+ pack_->Destroy();
+ delete features_;
+ delete service_locator_;
+ delete renderer_;
+ }
+
+ Pack* pack() { return pack_; }
+
+ ServiceDependency<ObjectManager> object_manager_;
+ ServiceLocator* service_locator_;
+ Features* features_;
+ Pack* pack_;
+ MockRenderer* renderer_;
+};
+
+// Test that non PoT textures can't make render surfaces
+TEST_F(RenderSurfaceTest, NonPowerOfTwoRenderSurfaceEnabled) {
+ Texture2D* texture = pack()->CreateTexture2D(20, 32, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL == texture);
+}
+// Test that a render surface can be created
+TEST_F(RenderSurfaceTest, CreateRenderSurfaceFromTexture2D) {
+ Texture2D* texture = pack()->CreateTexture2D(16, 32, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL != texture);
+
+ RenderSurface::Ref render_surface = texture->GetRenderSurface(0);
+ ASSERT_TRUE(NULL != render_surface);
+ ASSERT_TRUE(NULL != render_surface->texture());
+ ASSERT_EQ(render_surface->width(), 16);
+ ASSERT_EQ(render_surface->height(), 32);
+}
+
+TEST_F(RenderSurfaceTest, CreateRenderSurfaceFromTextureCUBE) {
+ TextureCUBE* texture = pack()->CreateTextureCUBE(16, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL != texture);
+
+ RenderSurface::Ref render_surface = texture->GetRenderSurface(
+ TextureCUBE::CubeFace::FACE_POSITIVE_X, 0);
+ ASSERT_TRUE(NULL != render_surface);
+ ASSERT_TRUE(NULL != render_surface->texture());
+ ASSERT_EQ(render_surface->width(), 16);
+ ASSERT_EQ(render_surface->height(), 16);
+}
+
+TEST_F(RenderSurfaceTest, SwapRenderSurfaces) {
+ Texture2D* texture = pack()->CreateTexture2D(16, 32, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL != texture);
+
+ RenderSurface::Ref render_surface = texture->GetRenderSurface(0);
+ ASSERT_TRUE(NULL != render_surface);
+ ASSERT_TRUE(texture == render_surface->texture());
+
+ RenderDepthStencilSurface* depth_surface =
+ pack()->CreateDepthStencilSurface(16, 32);
+
+ // Now swap surfaces.
+ renderer()->SetRenderSurfaces(render_surface, depth_surface);
+ const RenderSurface* test_render_surface = NULL;
+ const RenderDepthStencilSurface* test_depth_surface = NULL;
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ ASSERT_TRUE(test_render_surface == render_surface);
+ ASSERT_TRUE(test_depth_surface == depth_surface);
+}
+
+TEST_F(RenderSurfaceTest, SetBackSurfaces) {
+ Texture2D* texture = pack()->CreateTexture2D(16, 32, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL != texture);
+
+ RenderSurface::Ref render_surface = texture->GetRenderSurface(0);
+ ASSERT_TRUE(NULL != render_surface);
+ ASSERT_TRUE(texture == render_surface->texture());
+
+ RenderDepthStencilSurface* depth_surface =
+ pack()->CreateDepthStencilSurface(16, 32);
+
+ // Save the original surfaces for comparison.
+ const RenderSurface* original_render_surface = NULL;
+ const RenderDepthStencilSurface* original_depth_surface = NULL;
+ renderer()->GetRenderSurfaces(&original_render_surface,
+ &original_depth_surface);
+ // Now swap surfaces.
+ renderer()->SetRenderSurfaces(render_surface, depth_surface);
+ // Return the back buffers
+ renderer()->SetRenderSurfaces(NULL, NULL);
+ // Get the original surfaces again for comparison.
+ const RenderSurface* restored_render_surface = NULL;
+ const RenderDepthStencilSurface* restored_depth_surface = NULL;
+ renderer()->GetRenderSurfaces(&original_render_surface,
+ &original_depth_surface);
+ ASSERT_TRUE(original_render_surface == restored_render_surface);
+ ASSERT_TRUE(original_depth_surface == restored_depth_surface);
+}
+
+TEST_F(RenderSurfaceTest, RenderSurfaceSetTest) {
+ Texture2D* texture = pack()->CreateTexture2D(16, 32, Texture::ARGB8, 2, true);
+ ASSERT_TRUE(NULL != texture);
+
+ RenderSurface::Ref render_surface = texture->GetRenderSurface(0);
+ ASSERT_TRUE(NULL != render_surface);
+ ASSERT_TRUE(texture == render_surface->texture());
+
+ RenderDepthStencilSurface* depth_surface =
+ pack()->CreateDepthStencilSurface(16, 32);
+
+ RenderSurfaceSet* render_surface_set = pack()->Create<RenderSurfaceSet>();
+ render_surface_set->set_render_surface(render_surface);
+ render_surface_set->set_render_depth_stencil_surface(depth_surface);
+ ASSERT_TRUE(render_surface_set->ValidateBoundSurfaces());
+
+ RenderContext render_context(g_renderer);
+
+ const RenderSurface* old_render_surface = NULL;
+ const RenderDepthStencilSurface* old_depth_surface = NULL;
+ renderer()->GetRenderSurfaces(&old_render_surface, &old_depth_surface);
+
+ render_surface_set->Render(&render_context);
+ const RenderSurface* test_render_surface = NULL;
+ const RenderDepthStencilSurface* test_depth_surface = NULL;
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ ASSERT_TRUE(test_render_surface == render_surface);
+ ASSERT_TRUE(test_depth_surface == depth_surface);
+
+ render_surface_set->PostRender(&render_context);
+ renderer()->GetRenderSurfaces(&test_render_surface, &test_depth_surface);
+ ASSERT_TRUE(test_render_surface == old_render_surface);
+ ASSERT_TRUE(test_depth_surface == old_depth_surface);
+}
+
+} // namespace o3d
+
diff --git a/o3d/core/cross/renderer.h b/o3d/core/cross/renderer.h
index 54ea1ca..8c6f65d 100644
--- a/o3d/core/cross/renderer.h
+++ b/o3d/core/cross/renderer.h
@@ -513,6 +513,11 @@ class Renderer {
// current platform.
virtual const int* GetRGBAUByteNSwizzleTable() = 0;
+ // Used only for unit testing purposes. Should not be used elsewhere.
+ void set_rendering(bool rendering) {
+ rendering_ = rendering;
+ }
+
protected:
typedef vector_map<String, StateHandler*> StateHandlerMap;
typedef std::vector<ParamVector> ParamVectorArray;