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