예제 #1
0
void RenderDialog::layout()
{
    LayoutRepainter repainter(*this, true);
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());

    RenderBlock::layout();

    RenderStyle* styleToUse = style();
    if (styleToUse->position() != AbsolutePosition || !styleToUse->top().isAuto() || !styleToUse->bottom().isAuto()) {
        statePusher.pop();
        return;
    }

    // Adjust the dialog's position to be centered in or at the top of the viewport.
    // FIXME: Figure out what to do in vertical writing mode.
    FrameView* frameView = document()->view();
    int scrollTop = frameView->scrollOffset().height();
    FloatPoint absolutePoint(0, scrollTop);
    int visibleHeight = frameView->visibleContentRect(true).height();
    if (height() < visibleHeight)
        absolutePoint.move(0, (visibleHeight - height()) / 2);
    FloatPoint localPoint = containingBlock()->absoluteToLocal(absolutePoint);
    LayoutUnit localTop = LayoutSize(localPoint.x(), localPoint.y()).height();
    setY(localTop);

    statePusher.pop();
    // FIXME: Since there is always a layer here, repainter shouldn't be necessary. But without it, the dialog is sometimes not painted (see bug 90670).
    repainter.repaintAfterLayout();
}
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    bool hadTransform = hasTransform();

    RenderObject::styleDidChange(diff, oldStyle);
    updateFromStyle();

    LayerType type = layerTypeRequired();
    if (type != NoLayer) {
        if (!layer()) {
            createLayer(type);
            if (parent() && !needsLayout()) {
                // FIXME: This invalidation is overly broad. We should update to
                // do the correct invalidation at RenderStyle::diff time. crbug.com/349061
                layer()->renderer()->setShouldDoFullPaintInvalidation(true);
                // FIXME: We should call a specialized version of this function.
                layer()->updateLayerPositionsAfterLayout();
            }
        }
    } else if (layer() && layer()->parent()) {
        setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
        layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
        if (hadTransform)
            setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
    }

    if (layer()) {
        // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
        // from the style.
        layer()->setLayerType(type);
        layer()->styleChanged(diff, oldStyle);
    }
}
예제 #3
0
IntRect RenderView::documentRect() const
{
    FloatRect overflowRect(unscaledDocumentRect());
    if (hasTransform())
        overflowRect = layer()->currentTransform().mapRect(overflowRect);
    return IntRect(overflowRect);
}
예제 #4
0
void RenderMedia::layout()
{
    IntSize oldSize = contentBoxRect().size();

    RenderImage::layout();

    RenderBox* controlsRenderer = m_controls->renderBox();
    if (!controlsRenderer)
        return;
    IntSize newSize = contentBoxRect().size();
    if (newSize == oldSize && !controlsRenderer->needsLayout())
        return;

    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or 
    // call view()->disableLayoutState().  Since using a LayoutStateMaintainer is slightly more efficient,
    // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());

    controlsRenderer->setLocation(borderLeft() + paddingLeft(), borderTop() + paddingTop());
    controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
    controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
    controlsRenderer->setNeedsLayout(true, false);
    controlsRenderer->layout();
    setChildNeedsLayout(false);

    statePusher.pop();
}
예제 #5
0
void RenderVTTCue::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    RenderBlockFlow::layout();

#if ENABLE(WEBVTT_REGIONS)
    // If WebVTT Regions are used, the regular WebVTT layout algorithm is no
    // longer necessary, since cues having the region parameter set do not have
    // any positioning parameters. Also, in this case, the regions themselves
    // have positioning information.
    if (!m_cue->regionId().isEmpty())
        return;
#endif

    LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
    
    if (m_cue->cueType()== TextTrackCue::WebVTT) {
        if (toVTTCue(m_cue)->snapToLines())
            repositionCueSnapToLinesSet();
        else
            repositionCueSnapToLinesNotSet();
    } else
        repositionGenericCue();

    statePusher.pop();
}
예제 #6
0
int RenderView::docRight() const
{
    IntRect overflowRect(layoutOverflowRect());
    flipForWritingMode(overflowRect);
    if (hasTransform())
        overflowRect = layer()->currentTransform().mapRect(overflowRect);
    return overflowRect.maxX();
}
예제 #7
0
int RenderView::docTop() const
{
    IntRect overflowRect(0, minYLayoutOverflow(), 0, maxYLayoutOverflow() - minYLayoutOverflow());
    flipForWritingMode(overflowRect);
    if (hasTransform())
        overflowRect = layer()->currentTransform().mapRect(overflowRect);
    return overflowRect.y();
}
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    bool hadTransform = hasTransform();

    RenderObject::styleDidChange(diff, oldStyle);
    updateFromStyle();

    LayerType type = layerTypeRequired();
    if (type != NoLayer) {
        if (!layer() && layerCreationAllowedForSubtree()) {
            if (s_wasFloating && isFloating())
                setChildNeedsLayout();
            createLayer(type);
            if (parent() && !needsLayout() && containingBlock()) {
                // FIXME: This invalidation is overly broad. We should update to
                // do the correct invalidation at RenderStyle::diff time. crbug.com/349061
                if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
                    layer()->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true);
                else
                    layer()->repainter().setRepaintStatus(NeedsFullRepaint);
                // Hit in animations/interpolation/perspective-interpolation.html
                // FIXME: I suspect we can remove this assert disabler now.
                DisableCompositingQueryAsserts disabler;
                layer()->updateLayerPositionRecursive();
            }
        }
    } else if (layer() && layer()->parent()) {
        setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
        setHasReflection(false);
        layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
        if (s_wasFloating && isFloating())
            setChildNeedsLayout();
        if (hadTransform)
            setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
    }

    if (layer()) {
        // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
        // from the style.
        layer()->setLayerType(type);
        layer()->styleChanged(diff, oldStyle);
    }

    if (FrameView *frameView = view()->frameView()) {
        bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
        bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
        if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
            if (newStyleIsViewportConstained && layer())
                frameView->addViewportConstrainedObject(this);
            else
                frameView->removeViewportConstrainedObject(this);
        }
    }
}
예제 #9
0
void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
{
    ASSERT(needsLayout());

    if (!relayoutChildren && simplifiedLayout())
        return;

    // FIXME: Much of this method is boiler plate that matches RenderBox::layoutBlock and Render*FlexibleBox::layoutBlock.
    // It would be nice to refactor some of the duplicate code.
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());

    if (inRenderFlowThread()) {
        // Regions changing widths can force us to relayout our children.
        if (logicalWidthChangedInRegions())
            relayoutChildren = true;
    }
    computeInitialRegionRangeForBlock();

    LayoutSize previousSize = size();

    setLogicalHeight(0);
    computeLogicalWidth();

    m_overflow.clear();

    layoutGridItems();

    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
    computeLogicalHeight();

    if (size() != previousSize)
        relayoutChildren = true;

    layoutPositionedObjects(relayoutChildren || isRoot());

    computeRegionRangeForBlock();

    computeOverflow(oldClientAfterEdge);
    statePusher.pop();

    updateLayerTransform();

    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
    // we overflow or not.
    if (hasOverflowClip())
        layer()->updateScrollInfoAfterLayout();

    repainter.repaintAfterLayout();

    setNeedsLayout(false);
}
예제 #10
0
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    bool hadTransform = hasTransform();
    bool hadLayer = hasLayer();
    bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer();

    RenderObject::styleDidChange(diff, oldStyle);
    updateFromStyle();

    LayerType type = layerTypeRequired();
    if (type != NoLayer) {
        if (!layer() && layerCreationAllowedForSubtree()) {
            if (s_wasFloating && isFloating())
                setChildNeedsLayout();
            createLayer(type);
            if (parent() && !needsLayout()) {
                // FIXME: We should call a specialized version of this function.
                layer()->updateLayerPositionsAfterLayout();
            }
        }
    } else if (layer() && layer()->parent()) {
        setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
        setHasReflection(false);
        layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
        if (s_wasFloating && isFloating())
            setChildNeedsLayout();
        if (hadTransform)
            setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation();
    }

    if (layer()) {
        // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer
        // from the style.
        layer()->setLayerType(type);

        layer()->styleChanged(diff, oldStyle);
        if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting)
            setChildNeedsLayout();
    }

    if (FrameView *frameView = view()->frameView()) {
        bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
        bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
        if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
            if (newStyleIsViewportConstained && layer())
                frameView->addViewportConstrainedObject(this);
            else
                frameView->removeViewportConstrainedObject(this);
        }
    }
}
예제 #11
0
void VsVariableWithMesh::createTransformedVariableAndMesh() {
  VsLog::debugLog() <<"VsVariableWithMesh::createTransformedVariableAndMesh() - Creating transformed var name." <<std::endl;
  
  // Does this variable have a transformation?
  if (hasTransform()) {
    VsLog::debugLog()<<"VsVariableWithMesh::createTransformedVariableAndMesh() - registering transformed variable: " + getFullTransformedName() <<std::endl;
    registry->registerTransformedVarName(getFullTransformedName(), getFullName());
    
    //And register the transformed mesh name to match
    registry->registerTransformedMeshName(getFullTransformedName(), getFullName());
  }
  
  VsLog::debugLog() <<"VsVariableWithMesh::createTransformedVariable() - returning." <<std::endl;
}
예제 #12
0
void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
{
    s_wasFloating = isFloating();
    s_hadLayer = hasLayer();
    s_hadTransform = hasTransform();
    if (s_hadLayer)
        s_layerWasSelfPainting = layer()->isSelfPaintingLayer();

    // If our z-index changes value or our visibility changes,
    // we need to dirty our stacking context's z-order list.
    RenderStyle* oldStyle = style();
    if (oldStyle && newStyle) {
        if (parent()) {
            // Do a repaint with the old style first, e.g., for example if we go from
            // having an outline to not having an outline.
            if (diff == StyleDifferenceRepaintLayer) {
                layer()->repaintIncludingDescendants();
                if (!(oldStyle->clip() == newStyle->clip()))
                    layer()->clearClipRectsIncludingDescendants();
            } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < oldStyle->outlineSize())
                repaint();
        }

        if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
            // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
            // end up being destroyed.
            if (hasLayer()) {
                if (oldStyle->position() != newStyle->position()
                    || oldStyle->zIndex() != newStyle->zIndex()
                    || oldStyle->hasAutoZIndex() != newStyle->hasAutoZIndex()
                    || !(oldStyle->clip() == newStyle->clip())
                    || oldStyle->hasClip() != newStyle->hasClip()
                    || oldStyle->opacity() != newStyle->opacity()
                    || oldStyle->transform() != newStyle->transform()
#if ENABLE(CSS_FILTERS)
                    || oldStyle->filter() != newStyle->filter()
#endif
                    )
                layer()->repaintIncludingDescendants();
            } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
                // If we don't have a layer yet, but we are going to get one because of transform or opacity,
                //  then we need to repaint the old position of the object.
                repaint();
            }
        }
    }

    RenderObject::styleWillChange(diff, newStyle);
}
예제 #13
0
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
    bool hadTransform = hasTransform();
    bool hadLayer = hasLayer();
    bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer();

    RenderObject::styleDidChange(diff, oldStyle);
    updateFromStyle();

    if (requiresLayer()) {
        if (!layer() && layerCreationAllowedForSubtree()) {
            if (s_wasFloating && isFloating())
                setChildNeedsLayout();
            createLayer();
            if (parent() && !needsLayout() && containingBlock()) {
                layer()->repainter().setRepaintStatus(NeedsFullRepaint);
                // There is only one layer to update, it is not worth using |cachedOffset| since
                // we are not sure the value will be used.
                layer()->updateLayerPositions(0);
            }
        }
    } else if (layer() && layer()->parent()) {
        setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit.
        setHasReflection(false);
        layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
        if (s_wasFloating && isFloating())
            setChildNeedsLayout();
        if (hadTransform)
            setNeedsLayoutAndPrefWidthsRecalc();
    }

    if (layer()) {
        layer()->styleChanged(diff, oldStyle);
        if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting)
            setChildNeedsLayout();
    }

    if (FrameView *frameView = view()->frameView()) {
        bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
        bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
        if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
            if (newStyleIsViewportConstained && layer())
                frameView->addViewportConstrainedObject(this);
            else
                frameView->removeViewportConstrainedObject(this);
        }
    }
}
예제 #14
0
void RenderTextTrackCue::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    RenderBlock::layout();

    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
    
    if (m_cue->cueType()== TextTrackCue::WebVTT) {
        if (m_cue->snapToLines())
            repositionCueSnapToLinesSet();
        else
            repositionCueSnapToLinesNotSet();
    } else
        repositionGenericCue();

    statePusher.pop();
}
예제 #15
0
void VsVariableWithMesh::createComponents() {
  VsLog::debugLog() << __CLASS__ << __FUNCTION__ << "  " << __LINE__ << "  "
                    << "Entering" << std::endl;
  
  size_t numComps = getNumComps();
  
  //We should only create component names if we have more than one component
  //But i'm going to leave it as-is for now...
  bool transformExists = hasTransform();
  for (size_t i = 0; i < numComps; ++i) {
    registry->registerComponent(getFullName(), (int)i, getLabel(i));
    if (transformExists) {
      registry->registerComponent(getFullTransformedName(), (int)i, getLabel(i));
    }
  }

  VsLog::debugLog() << __CLASS__ << __FUNCTION__ << "  " << __LINE__ << "  "
                    << "Returning" << std::endl;
}
예제 #16
0
void RenderVTTCue::layout()
{
    LayoutRectRecorder recorder(*this);
    RenderBlockFlow::layout();

    // If WebVTT Regions are used, the regular WebVTT layout algorithm is no
    // longer necessary, since cues having the region parameter set do not have
    // any positioning parameters. Also, in this case, the regions themselves
    // have positioning information.
    if (!m_cue->regionId().isEmpty())
        return;

    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());

    if (m_cue->snapToLines())
        repositionCueSnapToLinesSet();
    else
        repositionCueSnapToLinesNotSet();

    statePusher.pop();
}
예제 #17
0
void RenderMedia::layout()
{
    StackStats::LayoutCheckPoint layoutCheckPoint;
    LayoutSize oldSize = contentBoxRect().size();

    RenderImage::layout();

    RenderBox* controlsRenderer = toRenderBox(m_children.firstChild());
    if (!controlsRenderer)
        return;

    bool controlsNeedLayout = controlsRenderer->needsLayout();
    // If the region chain has changed we also need to relayout the controls to update the region box info.
    // FIXME: We can do better once we compute region box info for RenderReplaced, not only for RenderBlock.
    const RenderFlowThread* flowThread = flowThreadContainingBlock();
    if (flowThread && !controlsNeedLayout) {
        if (flowThread->pageLogicalSizeChanged())
            controlsNeedLayout = true;
    }

    LayoutSize newSize = contentBoxRect().size();
    if (newSize == oldSize && !controlsNeedLayout)
        return;

    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or 
    // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
    // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());

    controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
    controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
    controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
    controlsRenderer->setNeedsLayout(true, MarkOnlyThis);
    controlsRenderer->layout();
    setChildNeedsLayout(false);

    statePusher.pop();
}
예제 #18
0
   bool MeshMetadata::read(vlsv::Reader* vlsvReader,const std::map<std::string,std::string>& attribs) {
      // Check that reader exists:
      if (vlsvReader == NULL) return false;
      
      bool success = true;
      map<string,string>::const_iterator it;
      
      // Get mandatory mesh parameters
      // Get mesh name:
      it = attribs.find("name"); 
      if (it == attribs.end()) {
         debug3 << "VLSV\t\t ERROR: XML tag does have attribute 'name'" << endl;
         success = false; 
      } else {
         name = it->second;
      }
      
      // Get arraysize, vectorsize, datasize, datatype:
      it = attribs.find("arraysize"); 
      if (it == attribs.end()) {
         debug3 << "VLSV\t\t ERROR: XML tag does have attribute 'arraysize'" << endl;
         success = false;
      } else {
         arraySize = atoi(it->second.c_str());
      }
      
      it = attribs.find("vectorsize");
      if (it == attribs.end()) {
         debug3 << "VLSV\t\t ERROR: XML tag does have attribute 'vectorsize'" << endl;
         success = false;
      } else {
         vectorSize = atoi(it->second.c_str());
      }
      
      it = attribs.find("datasize");
      if (it == attribs.end()) {
         debug3 << "VLSV\t\t ERROR: XML tag does have attribute 'datasize'" << endl;
         success = false;
      } else {
         dataSize = atoi(it->second.c_str());
      }
      
      it = attribs.find("datatype");
      if (it == attribs.end()) {
         debug3 << "VLSV\t\t ERROR: XML tag does have attribute 'datatype'" << endl;
         success = false;
      } else {
         datatype = vlsv::getVLSVDatatype(it->second);
      }

      // Get optional mesh parameters:
      transformName = "";
      it = attribs.find("xlabel"); if (it != attribs.end()) xLabel = it->second;
      it = attribs.find("ylabel"); if (it != attribs.end()) yLabel = it->second;
      it = attribs.find("zlabel"); if (it != attribs.end()) zLabel = it->second;
      it = attribs.find("xunits"); if (it != attribs.end()) xUnits = it->second;
      it = attribs.find("yunits"); if (it != attribs.end()) yUnits = it->second;
      it = attribs.find("zunits"); if (it != attribs.end()) zUnits = it->second;
      it = attribs.find("xperiodic"); if (it != attribs.end()) if (it->second == "yes") xPeriodic = true;
      it = attribs.find("yperiodic"); if (it != attribs.end()) if (it->second == "yes") yPeriodic = true;
      it = attribs.find("zperiodic"); if (it != attribs.end()) if (it->second == "yes") zPeriodic = true;
      it = attribs.find("max_refinement_level"); if (it != attribs.end()) maxRefinementLevel = atoi(it->second.c_str());
      it = attribs.find("transform"); if (it != attribs.end()) transformName = it->second;

      // Read the transform matrix, if defined:
      if (hasTransform() == true) {
         // Attempt to read transform matrix tag:
         list<pair<string,string> > attribsIn;
         map<string,string> attribsOut;

         attribsIn.push_back(make_pair("name",transformName));
         if (vlsvReader->getArrayAttributes("TRANSFORM",attribsIn,attribsOut) == false) {
            debug3 << "VLSV\t\t ERROR: Failed to read array 'TRANSFORM' attributes for mesh '" << getName() << "' from VLSV file" << endl;
            transformName = ""; return false;
         }

         // Check arraysize and vectorsize for correctness:
         map<string,string>::const_iterator xml = attribsOut.find("arraysize");
         if (atoi(xml->second.c_str()) != 16) {
            debug3 << "VLSV\t\t ERROR: Transform matrix has wrong arraysize '" << atoi(xml->second.c_str()) << "', should be 16" << endl;
            transformName = ""; return false;
         }
         
         xml = attribsOut.find("vectorsize");
         if (atoi(xml->second.c_str()) != 1) {
            debug3 << "VLSV\t\t ERROR: Transform matrix has wrong vectorsize '" << atoi(xml->second.c_str()) << "', should be 1" << endl;
            transformName = ""; return false;
         }

         // Read the matrix components:
         double* ptr = transform;
         if (vlsvReader->read("TRANSFORM",attribsIn,0,16,ptr,false) == false) {
            debug3 << "VLSV\t\t ERROR: Failed to read the transform matrix for mesh '" << getName() << "'" << endl;
            transformName = ""; return false;
         }
      }

      return success;
   }
예제 #19
0
void PrimitiveShader_PC::Flush()
{
    if(buffer_.empty())
        return;
    auto renderer = getRenderer();
    Use();
    CheckGL();

    // Send our transformation to the currently bound shader,
    // in the "MVP" uniform
    auto const &pv = renderer->getCamera().getPV();
    glEnable(GL_BLEND);
    if(hasTransform()){
        //m[0][2],m[1][2] is always 0
        auto const &m = getTransform();
        auto pv2 = pv * Mat4(Vec4(m[0][0],m[0][1],0,m[0][2]),
                Vec4(m[1][0],m[1][1],0,m[1][2]),
                Vec4(0,0,1,0),
                Vec4(m[2][0],m[2][1],0,m[2][2]));
        glUniformMatrix4fv(pv_, 1, GL_FALSE, &pv2[0][0]);
    }else{
        glUniformMatrix4fv(pv_, 1, GL_FALSE, &pv[0][0]);
    }
    CheckGL();

    glBindBuffer(GL_ARRAY_BUFFER, vbo_);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Point)*buffer_.size(), (const void*)&buffer_[0], GL_DYNAMIC_DRAW);
    CheckGL();

    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(model_xy_);
    glVertexAttribPointer(
            model_xy_,                  // attribute. No particular reason for 0, but must match the layout in the shader.
            2,                  // size
            GL_FLOAT,           // type
            GL_FALSE,           // normalized?
            sizeof(Point),      // stride
            (void*)0            // array buffer offset
            );
    CheckGL();

    // 2nd attribute buffer : color
    glEnableVertexAttribArray(color_);
    glVertexAttribPointer(
            color_,
            4,
            GL_FLOAT,
            GL_FALSE,
            sizeof(Point),
            (void*)(2*sizeof(GLfloat))
            );
    CheckGL();
    glEnable(GL_PROGRAM_POINT_SIZE);
    glDrawArrays((GLenum)drawMode_, 0, buffer_.size());
    glDisable(GL_PROGRAM_POINT_SIZE);
    CheckGL();

    glDisableVertexAttribArray(model_xy_);
    glDisableVertexAttribArray(color_);

    glDisable(GL_BLEND);
    Unuse();
    buffer_.clear();
    renderer->addRenderCall();
}