void RenderViewMLGPU::Prepare() {
  if (!mTarget) {
    return;
  }

  // Prepare front-to-back passes. These are only present when using the depth
  // buffer, and they contain only opaque data.
  for (RefPtr<RenderPassMLGPU>& pass : mFrontToBack) {
    pass->PrepareForRendering();
  }

  // Prepare the Clear buffer, which will fill the render target with
  // transparent pixels. This must happen before we set up world constants,
  // since it can create new z-indices.
  PrepareClears();

  // Prepare the world constant buffer. This must be called after we've
  // finished allocating all z-indices.
  {
    WorldConstants vsConstants;
    Matrix4x4 projection = Matrix4x4::Translation(-1.0, 1.0, 0.0);
    projection.PreScale(2.0 / float(mTarget->GetSize().width),
                        2.0 / float(mTarget->GetSize().height), 1.0f);
    projection.PreScale(1.0f, -1.0f, 1.0f);

    memcpy(vsConstants.projection, &projection._11, 64);
    vsConstants.targetOffset = Point(mTargetOffset);
    vsConstants.sortIndexOffset = PrepareDepthBuffer();
    vsConstants.debugFrameNumber =
        mBuilder->GetManager()->GetDebugFrameNumber();

    SharedConstantBuffer* shared = mDevice->GetSharedVSBuffer();
    if (!shared->Allocate(&mWorldConstants, vsConstants)) {
      return;
    }
  }

  // Prepare back-to-front passes. In depth buffer mode, these contain draw
  // calls that might produce transparent pixels. When using CPU-based occlusion
  // culling, all draw calls are back-to-front.
  for (RefPtr<RenderPassMLGPU>& pass : mBackToFront) {
    pass->PrepareForRendering();
  }

  // Now, process children.
  for (const auto& iter : mChildren) {
    iter->Prepare();
  }
}
Matrix4x4
ReadTransforms(const nsCSSValueList* aList,
               nsStyleContext* aContext,
               nsPresContext* aPresContext,
               RuleNodeCacheConditions& aConditions,
               TransformReferenceBox& aRefBox,
               float aAppUnitsPerMatrixUnit,
               bool* aContains3dTransform)
{
  Matrix4x4 result;

  for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
    const nsCSSValue &currElem = curr->mValue;
    if (currElem.GetUnit() != eCSSUnit_Function) {
      NS_ASSERTION(currElem.GetUnit() == eCSSUnit_None &&
                   !aList->mNext,
                   "stream should either be a list of functions or a "
                   "lone None");
      continue;
    }
    NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1,
                 "Incoming function is too short!");

    /* Read in a single transform matrix. */
    MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext,
                               aPresContext, aConditions, aRefBox,
                               aContains3dTransform);
  }

  float scale = float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
  result.PreScale(1/scale, 1/scale, 1/scale);
  result.PostScale(scale, scale, scale);

  return result;
}
/* Helper function to set up a scale matrix. */
static void
ProcessScaleHelper(Matrix4x4& aMatrix,
                   float aXScale, 
                   float aYScale, 
                   float aZScale)
{
  aMatrix.PreScale(aXScale, aYScale, aZScale);
}
Matrix4x4
HostLayer::GetShadowTransform() {
  Matrix4x4 transform = mShadowTransform;
  Layer* layer = GetLayer();

  transform.PostScale(layer->GetPostXScale(), layer->GetPostYScale(), 1.0f);
  if (const ContainerLayer* c = layer->AsContainerLayer()) {
    transform.PreScale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
  }

  return transform;
}
Example #5
0
    /*
     * Scale this transform by [x], [y], and [z]. If [local] is true then
     * the operation is performed in local space, otherwise it is performed in world space.
     * If world space is used, it takes into account the  aggregated transform of the scene
     * object's ancestors.
     */
    void SceneObjectTransform::Scale(Real x, Real y, Real z, Bool local) {
        if (!local) {
            Matrix4x4 scaleMat;
            scaleMat.PreScale(x, y, z);
            Transform worldTrans;
            worldTrans.SetTo(scaleMat);

            Transform localTrans;
            GetLocalTransformationFromWorldTransformation(worldTrans, localTrans);

            this->TransformBy(localTrans);
        }
        else {
            Transform::Scale(x, y, z, true);
        }
    }
Example #6
0
void
TextRenderer::RenderText(const string& aText, const IntPoint& aOrigin,
                         const Matrix4x4& aTransform, uint32_t aTextSize,
                         uint32_t aTargetPixelWidth)
{
  EnsureInitialized();

  // For now we only have a bitmap font with a 16px cell size, so we just
  // scale it up if the user wants larger text.
  Float scaleFactor = Float(aTextSize) / Float(sCellHeight);

  aTargetPixelWidth /= scaleFactor;

  uint32_t numLines = 1;
  uint32_t maxWidth = 0;
  uint32_t lineWidth = 0;
  // Calculate the size of the surface needed to draw all the glyphs.
  for (uint32_t i = 0; i < aText.length(); i++) {
    // Insert a line break if we go past the TargetPixelWidth.
    // XXX - this has the downside of overrunning the intended width, causing
    // things at the edge of a window to be cut off.
    if (aText[i] == '\n' || (aText[i] == ' ' && lineWidth > aTargetPixelWidth)) {
      numLines++;
      lineWidth = 0;
      continue;
    }

    lineWidth += sGlyphWidths[uint32_t(aText[i])];
    maxWidth = std::max(lineWidth, maxWidth);
  }

  // Create a surface to draw our glyphs to.
  RefPtr<DataSourceSurface> textSurf =
    Factory::CreateDataSourceSurface(IntSize(maxWidth, numLines * sCellHeight), sTextureFormat);
  if (NS_WARN_IF(!textSurf)) {
    return;
  }

  DataSourceSurface::MappedSurface map;
  if (NS_WARN_IF(!textSurf->Map(DataSourceSurface::MapType::READ_WRITE, &map))) {
    return;
  }

  // Initialize the surface to transparent white.
  memset(map.mData, uint8_t(sBackgroundOpacity * 255.0f),
         numLines * sCellHeight * map.mStride);

  uint32_t currentXPos = 0;
  uint32_t currentYPos = 0;

  // Copy our glyphs onto the surface.
  for (uint32_t i = 0; i < aText.length(); i++) {
    if (aText[i] == '\n' || (aText[i] == ' ' && currentXPos > aTargetPixelWidth)) {
      currentYPos += sCellHeight;
      currentXPos = 0;
      continue;
    }

    uint32_t glyphXOffset = aText[i] % (sTextureWidth / sCellWidth) * sCellWidth * BytesPerPixel(sTextureFormat);
    uint32_t truncatedLine = aText[i] / (sTextureWidth / sCellWidth);
    uint32_t glyphYOffset =  truncatedLine * sCellHeight * mMap.mStride;

    for (int y = 0; y < 16; y++) {
      memcpy(map.mData + (y + currentYPos) * map.mStride + currentXPos * BytesPerPixel(sTextureFormat),
             mMap.mData + glyphYOffset + y * mMap.mStride + glyphXOffset,
             sGlyphWidths[uint32_t(aText[i])] * BytesPerPixel(sTextureFormat));
    }

    currentXPos += sGlyphWidths[uint32_t(aText[i])];
  }

  textSurf->Unmap();

  RefPtr<DataTextureSource> src = mCompositor->CreateDataTextureSource();

  if (!src->Update(textSurf)) {
    // Upload failed.
    return;
  }

  RefPtr<EffectRGB> effect = new EffectRGB(src, true, SamplingFilter::LINEAR);
  EffectChain chain;
  chain.mPrimaryEffect = effect;

  Matrix4x4 transform = aTransform;
  transform.PreScale(scaleFactor, scaleFactor, 1.0f);
  mCompositor->DrawQuad(Rect(aOrigin.x, aOrigin.y, maxWidth, numLines * 16),
                        IntRect(-10000, -10000, 20000, 20000), chain, 1.0f, transform);
}