Home | History | Annotate | Download | only in d3d9
      1 //
      2 // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
      8 
      9 #include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
     10 #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
     11 #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
     12 #include "libGLESv2/renderer/vertexconversion.h"
     13 #include "libGLESv2/renderer/BufferImpl.h"
     14 #include "libGLESv2/VertexAttribute.h"
     15 #include "libGLESv2/Buffer.h"
     16 
     17 namespace rx
     18 {
     19 
     20 VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer)
     21 {
     22     mVertexBuffer = NULL;
     23     mBufferSize = 0;
     24     mDynamicUsage = false;
     25 }
     26 
     27 VertexBuffer9::~VertexBuffer9()
     28 {
     29     SafeRelease(mVertexBuffer);
     30 }
     31 
     32 gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage)
     33 {
     34     SafeRelease(mVertexBuffer);
     35 
     36     updateSerial();
     37 
     38     if (size > 0)
     39     {
     40         DWORD flags = D3DUSAGE_WRITEONLY;
     41         if (dynamicUsage)
     42         {
     43             flags |= D3DUSAGE_DYNAMIC;
     44         }
     45 
     46         HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
     47 
     48         if (FAILED(result))
     49         {
     50             return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size);
     51         }
     52     }
     53 
     54     mBufferSize = size;
     55     mDynamicUsage = dynamicUsage;
     56     return gl::Error(GL_NO_ERROR);
     57 }
     58 
     59 VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer)
     60 {
     61     ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer));
     62     return static_cast<VertexBuffer9*>(vertexBuffer);
     63 }
     64 
     65 gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
     66                                                GLint start, GLsizei count, GLsizei instances, unsigned int offset)
     67 {
     68     if (!mVertexBuffer)
     69     {
     70         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
     71     }
     72 
     73     gl::Buffer *buffer = attrib.buffer.get();
     74 
     75     int inputStride = gl::ComputeVertexAttributeStride(attrib);
     76     int elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
     77 
     78     DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
     79 
     80     uint8_t *mapPtr = NULL;
     81 
     82     unsigned int mapSize;
     83     gl::Error error = spaceRequired(attrib, count, instances, &mapSize);
     84     if (error.isError())
     85     {
     86         return error;
     87     }
     88 
     89     HRESULT result = mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void**>(&mapPtr), lockFlags);
     90     if (FAILED(result))
     91     {
     92         return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result);
     93     }
     94 
     95     const uint8_t *input = NULL;
     96     if (attrib.enabled)
     97     {
     98         if (buffer)
     99         {
    100             BufferImpl *storage = buffer->getImplementation();
    101             input = static_cast<const uint8_t*>(storage->getData()) + static_cast<int>(attrib.offset);
    102         }
    103         else
    104         {
    105             input = static_cast<const uint8_t*>(attrib.pointer);
    106         }
    107     }
    108     else
    109     {
    110         input = reinterpret_cast<const uint8_t*>(currentValue.FloatValues);
    111     }
    112 
    113     if (instances == 0 || attrib.divisor == 0)
    114     {
    115         input += inputStride * start;
    116     }
    117 
    118     gl::VertexFormat vertexFormat(attrib, currentValue.Type);
    119     const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
    120     bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
    121 
    122     if (!needsConversion && inputStride == elementSize)
    123     {
    124         size_t copySize = static_cast<size_t>(count) * static_cast<size_t>(inputStride);
    125         memcpy(mapPtr, input, copySize);
    126     }
    127     else
    128     {
    129         d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
    130     }
    131 
    132     mVertexBuffer->Unlock();
    133 
    134     return gl::Error(GL_NO_ERROR);
    135 }
    136 
    137 gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances,
    138                                           unsigned int *outSpaceRequired) const
    139 {
    140     return spaceRequired(attrib, count, instances, outSpaceRequired);
    141 }
    142 
    143 unsigned int VertexBuffer9::getBufferSize() const
    144 {
    145     return mBufferSize;
    146 }
    147 
    148 gl::Error VertexBuffer9::setBufferSize(unsigned int size)
    149 {
    150     if (size > mBufferSize)
    151     {
    152         return initialize(size, mDynamicUsage);
    153     }
    154     else
    155     {
    156         return gl::Error(GL_NO_ERROR);
    157     }
    158 }
    159 
    160 gl::Error VertexBuffer9::discard()
    161 {
    162     if (!mVertexBuffer)
    163     {
    164         return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized.");
    165     }
    166 
    167     void *dummy;
    168     HRESULT result;
    169 
    170     result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
    171     if (FAILED(result))
    172     {
    173         return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal buffer for discarding, HRESULT: 0x%08x", result);
    174     }
    175 
    176     result = mVertexBuffer->Unlock();
    177     if (FAILED(result))
    178     {
    179         return gl::Error(GL_OUT_OF_MEMORY, "Failed to unlock internal buffer for discarding, HRESULT: 0x%08x", result);
    180     }
    181 
    182     return gl::Error(GL_NO_ERROR);
    183 }
    184 
    185 IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const
    186 {
    187     return mVertexBuffer;
    188 }
    189 
    190 gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances,
    191                                        unsigned int *outSpaceRequired) const
    192 {
    193     gl::VertexFormat vertexFormat(attrib, GL_FLOAT);
    194     const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat);
    195 
    196     if (attrib.enabled)
    197     {
    198         unsigned int elementCount = 0;
    199         if (instances == 0 || attrib.divisor == 0)
    200         {
    201             elementCount = count;
    202         }
    203         else
    204         {
    205             // Round up to divisor, if possible
    206             elementCount = rx::UnsignedCeilDivide(static_cast<unsigned int>(instances), attrib.divisor);
    207         }
    208 
    209         if (d3d9VertexInfo.outputElementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
    210         {
    211             if (outSpaceRequired)
    212             {
    213                 *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount;
    214             }
    215             return gl::Error(GL_NO_ERROR);
    216         }
    217         else
    218         {
    219             return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow.");
    220         }
    221     }
    222     else
    223     {
    224         const unsigned int elementSize = 4;
    225         if (outSpaceRequired)
    226         {
    227             *outSpaceRequired = elementSize * 4;
    228         }
    229         return gl::Error(GL_NO_ERROR);
    230     }
    231 }
    232 
    233 }
    234